I am building out a restaurant website and using Wagtail CMS Snippets for the owner to manage menu items. The list of menu items are getting rather long and I was wondering if there is any way to add a search input field to the Snippets admin window? Below is an annotated screenshot for visual reference. Thank you.
This can easily be solved by using Wagtail's ModelAdmin module (http://docs.wagtail.io/en/v1.8.1/reference/contrib/modeladmin/), all you need is to add this piece of code to your wagtail_hooks.py file:
from wagtail.contrib.modeladmin.options import (
ModelAdmin, modeladmin_register)
from .models import Product
class ProductAdmin(ModelAdmin):
model = Product
menu_label = 'Product' # ditch this to use verbose_name_plural from model
menu_icon = 'date' # change as required
menu_order = 200 # will put in 3rd place (000 being 1st, 100 2nd)
add_to_settings_menu = False # or True to add your model to the Settings sub-menu
exclude_from_explorer = False # or True to exclude pages of this type from Wagtail's explorer view
list_display = ('title', 'example_field2', 'example_field3', 'live')
list_filter = ('live', 'example_field2', 'example_field3')
search_fields = ('title',)
# Now you just need to register your customised ModelAdmin class with Wagtail
modeladmin_register(ProductAdmin)
It'll create a separate menu entry for your Products model that's customisable much like default Django Admin listing. Which means you can easily add different filters and sorters to a listing.
This is a very powerful feature and I myself don't show clients the "Snippets" section at all; it's just too simple and ugly. Instead, I create a separate ModelAdmin per snippet and this gives me the power of customisation.
The search bar will appear automatically once you set up your model to be indexed with the search system. You can do this by inheriting from the wagtail.wagtailsearch.index.Indexed class and defining a search_fields list on your model, as described here: http://docs.wagtail.io/en/v1.8.1/topics/search/indexing.html#wagtailsearch-indexing-models
(Note that if you're using Elasticsearch, you'll also need to run ./manage.py update_index to add the items to the search index.)
Related
I'm using PostgreSQL for the DB.
I have two models:
Project - can contain N Assets.
Asset - has a Foreign Key field that points to a Project. An Asset is related to 1 Project.
I want the user to be able to set the order of the Assets of a Project in the Django Admin in a handy way like ordering a list in the edit Project screen.
The order of the Assets is important in my business logic, but I don't want the user to set the order for each individual Asset (just to improve UX).
Is there a way to show a field in the Project admin screen that lists all the Assets that are related to the project and allows the user to order them as he wishes?
I did not find any solution to this other than adding a new field in the Asset modal to specify the order and handling the logic by myself (which is expected), however, I don't want it to be a field that has to be changed manually in each individual Asset.
By assuming your model structure:
Add a related_name in your Asset model
models.py:
# imports ..
class Project(model.Models):
# other fields
class Asset(model.Models):
project_linked = models.ForeignKey(Project, related_name='related_assets', on_delete=models.CASCADE)
Then use that to list and oder projects in the admin project listing page:
admin.py:
from django.contrib import admin
# import the Project model
class Projectadmin(admin.ModelAdmin):
list_display = ["related_assets"] # add any other desired fields from the Project model
ordering = ["any_fields from model"] # replace the field with your preference
admin.site.register(Project, Projectadmin)
Upon specifying ordering list, the admin will have a toggle button on top of specified fields to re-order them.
I am building an app in Django.
I found there is a very easy way to integrate a widget into django admin that allows the admin to filter model objects by fields values. That is achieved by including the line
list_filter = ['field_to_filter_by_its_values']
into the class mymodelAdmin(ImportExportModelAdmin) in admin.py, as shown below
class target_area_history_dataAdmin(ImportExportModelAdmin):
resource_class = target_area_history_dataResource
list_filter = ['Target_area_input_data__Name']
admin.site.register(target_area_history_data, target_area_history_dataAdmin)
Now, instead of integrate a widget to filter my model objects by that field, is there a way to integrate a widget to sort my model objects by that field?
Note: I am using Django Import-Export in my model.
I'll suggest you use django-treebeard. This allows you to view tree nodes hierarchically in the administration interface, with interface features dependent upon the tree algorithm used.
# admin.py
from django.contrib import admin
from treebeard.admin import TreeAdmin
from .models import Category
class CategoryAdmin(TreeAdmin):
list_display = ("title", "created", "modified",)
list_filter = ("created",)
admin.site.register(Category, CategoryAdmin)
What's cool about this is that you can not only sort (by clicking the header row) but also drag things around, as shown in this image.
I recommend you using the grapelli admin interface that allows what you need and a bit more. here you have the grapelli project page and the https://github.com/sehmaschine/django-grappelli.
It's a well documented package and is plug and play for what you need. It also gives a fresh face to Django Admin and is compatible with Django import/export package.
I'm trying to integrate Wagtail CMS with my existing Django project. Other than this basic installation, I made a file named wagtail_hooks.py. Everything's good so far, but I need to use WYSIWYG editor on Wagtail CMS. Is there a way to access models.py for Wagtail so that I can use third-party WYSIWYG editor on model level?
MY_APP/wagtail_hooks.py
from wagtail.contrib.modeladmin.options import (
ModelAdmin, modeladmin_register)
from .models import Store
class StoreAdmin(ModelAdmin):
model = Store
menu_label = 'Store' # ditch this to use verbose_name_plural from model
menu_icon = 'doc-full' # change as required
menu_order = 10 # will put in 3rd place (000 being 1st, 100 2nd)
add_to_settings_menu = False # or True to add your model to the Settings sub-menu
exclude_from_explorer = False # or True to exclude pages of this type from Wagtail's explorer view
list_display = ['id', 'status', 'typ', 'businessName',]
search_fields = ('businessName', 'created_by__username',)
# Now you just need to register your customised ModelAdmin class with Wagtail
modeladmin_register(StoreAdmin)
Wagtail comes with an excellent WYSIWYG editor, Draftail, based on DraftJS. It is highly extensible:
http://docs.wagtail.io/en/v2.4/advanced_topics/customisation/extending_draftail.html
To use it, you can change your model to use wagtail.core.fields.RichTextField instead of TextField.
There are several other WYSIWYG editors available, for example, you can still use the old editor with this setting:
WAGTAILADMIN_RICH_TEXT_EDITORS = {
'default': {
'WIDGET': 'wagtail.admin.rich_text.HalloRichTextArea'
}
}
Good luck!
If you are on the django admin page for the model Group. You don't know that there is a reverse relation to user.
Some people (not me) have difficulties with it.
Is there a way to show all reverse relations, so that you can jump to the matching admin pages?
Example:
On admin page for Group I want a link to User (and all other models which refer to it).
This should happen by code, not by hand with templates.
This method doesn't automatically add links to all related models of a Group, but does for all Users related to a Group (so for one related model at a time). With this you'll get an inline view in your Group with the related Users.
You could probably extend this technique to make it automatically work for all related fields.
class UserInline(admin.StackedInline):
model = User
extra = 0
readonly_fields = ('change',)
def change(self, instance):
if instance.id:
# Django's admin URLs are automatically constructed
# based on your Django app and model's name.
change_url = urlresolvers.reverse(
'admin:djangoapp_usermodel_change', args=(instance.id,)
)
return '<a class="changelink" href="{}">Change</a>'.format(change_url)
else:
return 'Save the group first before editing the user.'
change.allow_tags = True
class GroupAdmin(admin.ModelAdmin):
list_display = ('name',)
inlines = (UserInline,)
You might also be interested in this extension I created for Django admin pages to link to related objects:
https://github.com/gitaarik/django-admin-relation-links
It's quite easy to use and makes the admin a lot more convenient to use :).
My model looks like this:
class Asset(models.Model):
serial_number = models.CharField(max_length=100, unique=True)
asset_tag = models.CharField(max_length=100, unique=True)
class WorkOrder(models.Model):
asset = models.ForeignKey(Asset)
Essentially, a work order is submitted and then an admin assigns an asset to the work order. The asset_tag field is a barcode that we can scan in. When editing the work order in the Django admin, by default the asset field is displayed as a <select> widget. What we want to be able to do is have a search field so that we can scan the asset tag and then search for the right asset in the DB to associate with the work order.
I know you can customize the Django admin foreign key to a hard coded query, but I can't figure out how to get it so it does a search based on a field on the admin page.
Did you take a look at raw_id_fields?
It should be pretty to close to what you're after.
If you are using Django >= 2.0, you can take advantage of a feature called autocomplete_fields. You must define search_fields on the related object’s ModelAdmin because the autocomplete search uses it.
Since you have a ForeignKey relationship to Asset in WorkOrder, in the admin.py of your app add the following:
from django.contrib import admin
#admin.register(Asset)
class AssetAdmin(admin.ModelAdmin):
search_fields = ["serial_number", "asset_tag"]
#admin.register(WorkOrder)
class WorkOrderAdmin(admin.ModelAdmin):
autocomplete_fields = ["asset"]
Add the fields you want to use for searching to search_fields, and add define autocomplete_fields as shown in the code above.
Now you can use the autocomplete_fields from django 2.0.
It's quite neat.