64👍
Thanks @beholderrk, @gediminas and @jk-laiho! I packaged this into a reusable app.
Install:
pip install django-admin-list-filter-dropdown
Enable in settings.py
:
INSTALLED_APPS = (
...
'django_admin_listfilter_dropdown',
...
)
Use in admin.py
:
from django_admin_listfilter_dropdown.filters import (
DropdownFilter, ChoiceDropdownFilter, RelatedDropdownFilter
)
class EntityAdmin(admin.ModelAdmin):
...
list_filter = (
# for ordinary fields
('a_charfield', DropdownFilter),
# for choice fields
('a_choicefield', ChoiceDropdownFilter),
# for related fields
('a_foreignkey_field', RelatedDropdownFilter),
)
Here’s what it looks like:
41👍
I cannot comment answers so I’ll add to beholderrk’s answer here.
- create a new template called
dropdown_filter.html
or similar - copy the code of filter.html from feincms to
dropdown_filter.html
-
create a new filter class in
filters.py
:from django.contrib.admin.filters import AllValuesFieldListFilter class DropdownFilter(AllValuesFieldListFilter): template = 'admin/dropdown_filter.html'
-
now you can use this filter in your admin class:
class SomeAdmin(admin.ModelAdmin): # ... list_filter = (('country', DropdownFilter),)
Works great!
- [Django]-How can I return HTTP status code 204 from a Django view?
- [Django]-How do I create multiple model instances with Django Rest Framework?
- [Django]-"CSRF token missing or incorrect" while post parameter via AJAX in Django
33👍
Use filter.html from feincms
{% load i18n %}
<script type="text/javascript">var go_from_select = function(opt) { window.location = window.location.pathname + opt };</script>
<h3>{{ title }}</h3>
<ul class="admin-filter-{{ title|cut:' ' }}">
{% if choices|slice:"4:" %}
<li>
<select style="width: 95%;"
onchange="go_from_select(this.options[this.selectedIndex].value)">
{% for choice in choices %}
<option{% if choice.selected %} selected="selected"{% endif %}
value="{{ choice.query_string|iriencode }}">{{ choice.display }}</option>
{% endfor %}
</select>
</li>
{% else %}
{% for choice in choices %}
<li{% if choice.selected %} class="selected"{% endif %}>
<a href="{{ choice.query_string|iriencode }}">{{ choice.display }}</a></li>
{% endfor %}
{% endif %}
</ul>
- [Django]-How do I display the Django '__all__' form errors in the template?
- [Django]-How to update an existing Conda environment with a .yml file
- [Django]-Bulk create model objects in django
4👍
An easy option would be to use django-grappelli, which replaces all the filters with drop downs.
- [Django]-Django urls without a trailing slash do not redirect
- [Django]-Django's ModelForm unique_together validation
- [Django]-Django bulk_create with ignore rows that cause IntegrityError?
3👍
You can copy the admin templates from the django installation into you templates/admin folder in your project.
Then you will need to do any of 2 things in the forms or templates you want to show your outputs in:
-
If you are working with a form, in that you would like the list choices to be posted back to a database, you would in your model.py, on the field you have your choices, put in some this like this:
choice = forms.IntegerField(widget=forms.Select(choices=CHOICES))
-
If it is just to display on a page, then you will output on a template tag something like this:
<select> {% for choices in object.details.all %} <option> {{ object.choice }} </option> {% endfor %} </select>
- [Django]-Django values_list vs values
- [Django]-Django: reverse accessors for foreign keys clashing
- [Django]-How to reset migrations in Django 1.7
- [Django]-Django gives Bad Request (400) when DEBUG = False
- [Django]-RuntimeWarning: DateTimeField received a naive datetime
- [Django]-HTML – How to do a Confirmation popup to a Submit button and then send the request?
2👍
I am not a fan of all solutions provided up to now.
Why? If, for a field that you want to filter by, you have more than 10 values, a listview box isn’t that handy, too. I advice to use the standard search field capability of django admin which will show you a search field:
class BooksAdmin(admin.ModelAdmin):
list_display = ('ISBN', 'title')
search_fields = ('ISBN',)
# instead of: list_filter = ('ISBN',)
ordering = ('title',)
- [Django]-Get user information in django templates
- [Django]-Django, creating a custom 500/404 error page
- [Django]-How to use regex in django query
0👍
The best solution is to create a new template in admin/filter.html
and implement the HTML code suggested by @beholderrk. Just implemented it for a client and it works great.
Problem with DropdownFilter and RelatedDropdownFilter
is that it loses the proper display. Instead of the translated strings for Charfield(choices=xxx)
, it will show True
, False
and so on.
- [Django]-Django Aggregation – Expression contains mixed types. You must set output_field
- [Django]-How do I get the object if it exists, or None if it does not exist in Django?
- [Django]-Django: show the count of related objects in admin list_display
0👍
Could you please give a complete example. it shows like before.
here is my code
from django.contrib import admin
from pages.models import Post, Device, DeviceType, DeviceModel, Ipaddress, DeviceGroup, Location,Department,Comment
from django_admin_listfilter_dropdown.filters import DropdownFilter, RelatedDropdownFilter
class CommentInline(admin.TabularInline):
model = Comment
class IpaddressAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('ipaddress',)}
# model=Ipaddress
search_fields = ['ipaddress', ]
#
list_display = ('ipaddress', 'machinename', 'user', 'department','location',)
list_filter = (
('user', DropdownFilter),
('department', RelatedDropdownFilter),
('location', RelatedDropdownFilter),
)
- [Django]-Good ways to sort a queryset? – Django
- [Django]-Django get list of models in application
- [Django]-Default filter in Django admin
0👍
I was struggling with the same problem some few weeks back. So this answer might be useful to some developers from the future.
I managed to solve the problem by writing a custom template.html
I have bundled the code in an amazing package now that does the same for you, here’s the link.
Here’s how you can implement a Searchable Dropdown in place of the default List:
1. Installation:
pip install django-admin-searchable-dropdown
This command will install the latest version of the package in your project.
Now, include the package in your project by adding admin_searchable_dropdown
to your INSTALLED_APPS
inside settings.py
file.
2. Usage:
Let’s say you have following models:
from django.db import models
class CarCompany(models.Model):
name = models.CharField(max_length=128)
class CarModel(models.Model):
name = models.CharField(max_length=64)
company = models.ForeignKey(CarCompany, on_delete=models.CASCADE)
And you would like to filter results in CarModelAdmin
on the basis of company
. You need to define search_fields
in CarCompany
and then define filter like this:
from django.contrib import admin
from admin_searchable_dropdown.filters import AutocompleteFilter
class CarCompanyFilter(AutocompleteFilter):
title = 'Company' # display title
field_name = 'company' # name of the foreign key field
class CarCompanyAdmin(admin.ModelAdmin):
search_fields = ['name'] # this is required for django's autocomplete functionality
# ...
class CarModelAdmin(admin.ModelAdmin):
list_filter = [CarCompanyFilter]
# ...
After following these steps you may see the filter as:
- This is how the list filter is rendered in the form of a dropdown when the package is used
- And the dropdown filter is also Searchable
Features Offered:
- If you have large fields in Admin Filter, the sidebar gets widened, this package provides you the same list in a dropdown format, hence, no such hassle.
- If you have more than, say 20, field items, list filter is now a long side-pane, just ruining the admin interface. The Dropdown filter fixes that.
- The Dropdown is also "Searchable", with an input text field (which utilizes Django’s own
auto_complete
functionailty), so as long as the Django version you are using is greater than 2.0, you should be fine. - You can customize other
list_filters
you may have, like change the Title above the dropdown, or a custom Search logic etc. - You can customize Widget Texts to display in the Dropdown Option to use something other than the default
str(obj)
- [Django]-How do I reuse HTML snippets in a django view
- [Django]-How to check Django version
- [Django]-Why does Django's render() function need the "request" argument?
0👍
To add search functionality to @beholderrk and @Gediminas solution use the follow
Create searchable_dropdown_filter.html
in templates/admin
folder and paste the following code
{% load i18n %}
{% load static %}
<!-- Django's Select2 CSS -->
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/vendor/select2/select2.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/autocomplete.css' %}">
<!-- jQuery (Django Admin uses this, so you can refer to it) -->
<script src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>
<!-- Django's Select2 JS -->
<script src="{% static 'admin/js/vendor/select2/select2.full.js' %}"></script>
<script type="text/javascript">
$(document).ready(function() {
$('.searchable-select').select2();
});
var go_from_select = function(opt) { window.location = window.location.pathname + opt };
</script>
<h3>{{ title }}</h3>
<ul class="admin-filter-{{ title|cut:' ' }}">
{% if choices|slice:"4:" %}
<li>
<select style="width: 95%;"
onchange="go_from_select(this.options[this.selectedIndex].value)"
class="searchable-select"
>
{% for choice in choices %}
<option{% if choice.selected %} selected="selected"{% endif %}
value="{{ choice.query_string|iriencode }}">{{ choice.display }}</option>
{% endfor %}
</select>
</li>
{% else %}
{% for choice in choices %}
<li{% if choice.selected %} class="selected"{% endif %}>
<a href="{{ choice.query_string|iriencode }}">{{ choice.display }}</a></li>
{% endfor %}
{% endif %}
</ul>
In your admin.py
or filters.py
paste the following
from django.contrib.admin.filters import RelatedFieldListFilter
class SearchableDropdownFilter(RelatedFieldListFilter):
template = 'admin/searchable_dropdown_filter.html'
In your admin implementation use it as follows
class SomeAdmin(admin.ModelAdmin):
# ...
list_filter = (('country', SearchableDropdownFilter), ('city', SearchableDropdownFilter),)
This uses select2 to add search functionality to the dropdown. This is very handy when you have a ton of options you want to filter from.
- [Django]-Multiple django sites with apache & mod_wsgi
- [Django]-Homepage login form Django
- [Django]-Django Model – Get distinct value list