A simple Django app to render list filters in django admin using autocomplete widget.
A simple Django app to render list filters in django admin using an autocomplete widget. This app is heavily inspired by dal-admin-filters.
Django comes preshipped with an admin panel which is a great utility to create quick CRUD's. Version 2.0 came with a much needed
autocomplete_fieldsproperty which uses a select2 widget to load the options asynchronously. We leverage this in
django-admin-list-filter.
Requires Django version >= 2.0
You can install it via pip. To get the latest version clone this repo.
shell script pip install django-admin-autocomplete-filter
Add
admin_auto_filtersto your
INSTALLED_APPSinside settings.py of your project.
Let's say we have following models: ```python from django.db import models
class Artist(models.Model): name = models.CharField(max_length=128)
class Album(models.Model): name = models.CharField(maxlength=64) artist = models.ForeignKey(Artist, ondelete=models.CASCADE) cover = models.CharField(max_length=256, null=True, default=None) ```
And you would like to filter results in
AlbumAdminon the basis of
artist. You need to define
search fieldsin
Artistand then define filter like this:
from django.contrib import admin from admin_auto_filters.filters import AutocompleteFilterclass ArtistFilter(AutocompleteFilter): title = 'Artist' # display title field_name = 'artist' # name of the foreign key field
class ArtistAdmin(admin.ModelAdmin): search_fields = ['name'] # this is required for django's autocomplete functionality # ...
class AlbumAdmin(admin.ModelAdmin): list_filter = [ArtistFilter]
""" defining this class is required for AutocompleteFilter it's a bug and I am working on it. """ class Media: pass # ...
After following these steps you may see the filter as:
You can also register your custom view instead of using Django admin's
search_resultsto control the results in the autocomplete. For this you will need to create your custom view and register the URL in your admin class as shown below:
In your
views.py:
from admin_auto_filters.views import AutocompleteJsonViewclass CustomSearchView(AutocompleteJsonView): def get_queryset(self): """ your custom logic goes here. """ queryset = Artist.objects.all().order_by('name') return queryset
After this, register this view in your admin class:
from django.contrib import admin from django.urls import pathclass AlbumAdmin(admin.ModelAdmin): list_filter = [ArtistFilter]
class Media: pass def get_urls(self): urls = super().get_urls() custom_urls = [ path('custom_search/', self.admin_site.admin_view(CustomSearchView.as_view(model_admin=self)), name='custom_search'), ] return custom_urls + urls
Finally, just tell the filter class to use this new view:
from django.shortcuts import reverse from admin_auto_filters.filters import AutocompleteFilterclass ArtistFilter(AutocompleteFilter): title = 'Artist' field_name = 'artist'
def get_autocomplete_url(self, request, model_admin): return reverse('admin:custom_search')
It's also possible to use the
AutocompleteFilterFactoryshortcut to create filters on the fly, as shown below. Nested relations are supported too, with no need to specify the model.
from django.contrib import admin from admin_auto_filters.filters import AutocompleteFilterFactoryclass AlbumAdmin(admin.ModelAdmin): list_filter = [ AutocompleteFilterFactory('Artist', 'artist', 'admin:custom_search', True) ]
def get_urls(self): """As above..."""
You can customize the text displayed in the filter widget, to use something other than
str(obj). This needs to be configured for both the dropdown endpoint and the widget itself.
In your
views.py, override
display_text:
from admin_auto_filters.views import AutocompleteJsonViewclass CustomSearchView(AutocompleteJsonView):
@staticmethod def display_text(obj): return obj.my_str_method() def get_queryset(self): """As above..."""
Then use either of two options to customize the text.
Option one is to specify the form_field in an AutocompleteFilter in your
admin.py:
from django import forms from django.contrib import admin from django.shortcuts import reverse from admin_auto_filters.filters import AutocompleteFilterclass FoodChoiceField(forms.ModelChoiceField): def label_from_instance(self, obj): return obj.my_str_method()
class ArtistFilter(AutocompleteFilter): title = 'Artist' field_name = 'artist' form_field = FoodChoiceField
def get_autocomplete_url(self, request, model_admin): return reverse('admin:custom_search')
class AlbumAdmin(admin.ModelAdmin): list_filter = [ArtistFilter]
def get_urls(self): """As above..."""
Option two is to use an AutocompleteFilterFactory in your
admin.pyadd a
label_byargument:
from django.contrib import admin from admin_auto_filters.filters import AutocompleteFilterFactoryclass AlbumAdmin(admin.ModelAdmin): list_filter = [ AutocompleteFilterFactory('Artist', 'artist', 'admin:custom_search', True, label_by='my_str_method') ]
def get_urls(self): """As above..."""
This project is a combined effort of a lot of selfless developers who try to make things easier. Your contribution is most welcome.
Please make a pull-request to the branch
pre_release, make sure your branch does not have any conflicts, and clearly mention the problems or improvements your PR is addressing.
Django Admin Autocomplete Filter is an Open Source project licensed under the terms of the GNU GENERAL PUBLIC LICENSE.