Wagtail large list within stream field block - python

We use wagtail for our blogs that are part of an eCommerce site. When we want to add a product to the blog as it stands we have to put the exact product name in which then matches on save. As names can change this then breaks that blog which isnt ideal.
What we would like to do is add a field to our streamfield block that lets you pick from our list of products, however as we have 200k+ products and there might be up to 20 products on each blog loading the list into a dropdown is no good. What we need is to replicate what we do in Django admin using django-autocomplete-light where you start typing and get results based on that rather than loading the list into the HTML.
What we cant work out is how to do that within a streamfield block, I have seen libraries like "Wagtail Autocomplete" however it seems you can only use that as a panel rather than within a block. As far as we can see you can only use sub-classes of wagtail.core.blocks or they dont show up in the interface.
Any ideas?
Thanks in advance!

You can extend the editor. Although the examples are mainly focussed on adding CSS style, it still should be possible. You can read more on this at the documentation: http://docs.wagtail.io/en/v2.8/advanced_topics/customisation/extending_draftail.html#
Another option would be is to use the Wagtail autocomplete panel for specifying the product you need to reference to, in a seperate field of course. Then, using a regular f-string replacement, place the proper product details in the text.

Related

wagtail main search add modelAdmin models

Quick question on wagtail's main search at the top of the left sidebar beneath the logo.
By default that search box searches pages, images, documents, users.
Two questions:
Is there a way to modify that search scope so it also includes modelAdmin models?
Is there a way to remove pages from the search query list so it only searches images, documents, users?
I can't seem to find anything in the docs about it. I know you can search modelAdmin models once on the model admin list view, I have that working. I was just looking for a way to extend that search to be included on the main sidebar search as well.
Any direction you can provide would be much appreciated.
The admin search area does show multiple items, such as pages, images, documents etc.
However, this page only searches page models, when you click the other models (e.g. images), it will take you to the images search page, it will also append the query param q based on any existing search.
So just to clarify, this page only searches pages and to search for other items, it takes you elsewhere in the Wagtail admin.
Hopefully the below answers your specific scenario questions.
1. Modify the admin/pages search scope or results
This could possibly be done by making your own view, but it is not simple
You can see the search view function here https://github.com/wagtail/wagtail/blob/master/wagtail/admin/views/pages.py#L958
You can redirect any URL by modifying your urls.py to direct the admin/pages/search/ page to your custom view.
However, you would likely need to re-write (copy/paste) most of the view as it is a function, not class view
2. Adding custom search areas
This can be done by the register_admin_search_area hook, it will add (in a custom order) an item next to the 'other searches' text
See documentation here https://docs.wagtail.io/en/latest/reference/hooks.html#register-admin-search-area
This lets you add what is essentially a link to another search area elsewhere in the Wagtail admin (code example below)
3. Removing a search area
The simplest way to hide one of the items in the 'other searches' list would be with a CSS change
The next best way would be to customise the template wagtail/admin/templates/wagtailadmin/shared/search_other.html with an override and then filter the results
I am not aware of a way to remove hooks or registered hooks without some monkey patching, but the hooks get collected and stored as admin_search_areas you can see the code here - https://github.com/wagtail/wagtail/blob/master/wagtail/admin/search.py#L102
Example Code for using the register_admin_search_area hook
This basically uses the documentation example but gives you a rough idea of how to go to a specific ModelAdmin index view using this feature. Note: this does not search ALL ModelAdmin models, only one specific one.
You can always make a custom search page for searching all models at once though.
from wagtail.core import hooks
from wagtail.admin.search import SearchArea
# ...
#hooks.register('register_admin_search_area')
def register_model_admin_search_area():
# PeopleModelAdmin is a ModelAdmin also in the same hooks file
index_url = PeopleModelAdmin().url_helper.index_url
return SearchArea(
'People ModelAdmin',
index_url,
classnames='icon icon-user',
order=10000
)
#hooks.register('register_admin_search_area')
def register_snippets_search_area():
url = reverse('wagtailsnippets:list', args=('base', 'people'))
return SearchArea(
'People Snippets',
url,
classnames='icon icon-user',
order=10000
)

Django Editable Text Field

I've been able to easily create a list of editable items and manage them through the Django admin panel. That seems pretty simple and I have a good idea of how models work from other frameworks.
Although, I'm curious to know to know how I can make something as simple as editing a text area on a static site. Basically, I don't need to "add post" or anything of the sort. I just want to be able to edit a text area on a static site.
Any docs or examples?
I've been looking at packages such as django-flatblocks and chunks, these seem to possibly help with what I'd like to do. I'm just new to the Python world so some of this stuff is a little magic to me, especially involving the administration panel.
One thing that I realized is that these libraries (or apps in django?) seem to be super out of date, stemming back to the last commit being from 2012. Are these still commonly used?
Figured out a solution in case anyone is interested. I ended up using a Django application called django-generic-flatblocks which seems to provide me with what I need. Although, it's a bit strange as I had to replace all the text on my site with a gblock and then re-enter it all. Seems as if upon first creation of a block, it's empty so you essentially have to provide it with a value.
After that, if you log into the admin panel you're able to pull up the block and edit it. Alternatively, if you're logged into the Admin panel you're able to view your site and an edit tag is provided and you'll go directly to that block in the admin panel.
If anyone knows of anything which essentially allows me to define the text blocks up front in the admin panel then add the tags to the code, please lmk. I'd prefer to load all my content into the admin panel first and then just throw the tag into the code and have it display. That would save a lot of time in terms of having to copy the existing content, store it away, adding the tag, and then having to put it back in.
This seemed to be the only one of the recommended apps that worked for me. I tried to use Chunks because this really is only for title/text but on Django 1.11 it would freak out on me about not having South.db, which isn't even used.
https://github.com/bartTC/django-generic-flatblocks

Is possible with django-autocomplete-ligth to browse relateds objects

I would like to browse related objects in addition to search . like in the raw_id_field widget in the admin.
Is it possible with django-autocomplete-light?
Thanks!
Not with DAL, but you can certainly implement such thing. The article is about populating an HTML select field with a JS popup, but you can just omit that part and populate a text input instead like raw_id_field, all the rest of the article is valid for your case.

Global Variables in Django Admin Site

This was my original question, but it was not answered and so I thought Id post again with some of the strategies that I have tried, and be a little more specific.
I want to create a dynamic admin site, that based on if the field is blank or not will show that field. So I have a model that has a set number of fields, but for each individual entry will not contain all of the fields in my model and I want to exclude based on if that field is blank. My project is about bridges, and so to put it in practical terms I have a model that has every bridge part in it (this roughly is equivalent to 100), but each individual bridge (mapped to each unique brkey) will not have all 100 bridge parts. And so, I can prepopulate all of the fields it does have, but then the admin site has 100 other fields, and I would like to not display those fields that were not used on my admin site for that specific bridge, but those fields will differ with pretty much every bridge.
Like I said before, I have a unique bridge identifier(a unique 15 digit string), that correlates to each bridge, and then all of the various different variables that describe the bridge.
I have it set up now that the user will go to a url with the unique bridgekey and then this will create an entry of that bridge. So (as i am testing on my local machine) it would be like localhost/home/brkey and that code in my views.py that corresponds to that url is
Is this a final route that I have to take? I am very new to JavaScript and so I do not want to take this route but I will if I have to. Also does Django use Javascript in anyway that is syntactically different? If so I cannot find any Django documentation on incorporating Javascript into my admin site.
A final option that I have exhausted is to use global variables. Instead of having the url that creates the entry in my Views.py, I placed it in my admins.py, and had my modelAdmin class in there as well, so like this.
admins.py
-set up global variable
bridgekey_unique = " "
If I can find a way to either pass that unique bridge key to my modelAdmin class, or figure out if that said field is blank because the bridge doesnt have that part, I will be able to achieve what I want without using Javascript. I have tried a lot of variations of all two of theses strategies to no avail, but have not tried the JavaScript idea as I dont really know any javascript at all.
Sorry for the lengthy post, but people said I wasnt specific enough. Any help would be greatly appreciated.
I didn't read all of that - sorry, there's too much. But I did notice your comment that you expect to access in your modeladmin definition a variable that you set in your view. That can't possibly work.
Anything at class level is always executed when the module containing the class is first imported. That is when the server process starts up, so there is no possible way anything done in the view can have happened yet.
You almost never want to have any logic at class level. You need to put it in methods, which are called at the relevant time. In this case, you probably need to use the get_fields method.
Edit
Looking further up at your attempt at a get_fields method, I can't see at all what you are trying to do here. 'prestressed_concrete_deck' is a literal string, and could never be None, so neither of your conditions can ever be true. And as to your question about what the parameters are, the documentation for that method explains clearly that obj is the object being edited.

Django admin site: how to create a single page for global settings?

I would like to create a single page in the admin site of django where I can change some global variables of the website (title of the website, items in the navigation menu, etc). At the moment I have them coded as context processors but I would like to make them editable. Something similar to what happens in WordPress.
Is this possible?
I can store the data in the databse, but can I have a link in the admin site that goes straight to the first document record and doesnt allow the creation of multiple records (they wouldnt make sense)
Instead of creating a model in the database, would it be possible to change some context_processor from the admin site (I think this would be best)
django-preferences does exactly what you are looking for. The implementation is a bit hacky (particularly the setting of __module__ on the model class to trick Django into thinking it was loaded from a different app), but it works.
This sounds like what the sites framework is intended to help with.
http://docs.djangoproject.com/en/stable/ref/contrib/sites/
"It’s a hook for associating objects and functionality to particular Web sites, and it’s a holding place for the domain names and “verbose” names of your Django-powered sites."
The docs make it sound like it's only good for multiple sites, but it's a great place to put stuff in a single-site-per-django model too.
There's an app called django-values that allows you storing of specific settings in the database.

Categories