Hello,
this is my first post but I use django for some years. I tried to search this question without finding results.
I have a small app of type “Countries => City” as reported below:
# models.py
class Country(models.Model):
name = models.CharField(max_length=150, help_text="Country name")
iso2 = models.CharField(max_length=2, help_text="Country ISO2")
iso3 = models.CharField(max_length=3, help_text="Country ISO3")
class City(models.Model):
name = models.CharField(max_length=150, help_text="City name")
country = models.ForeignKey('Country', on_delete=models.SET_NULL, null=True, blank=True)
and in admin.py
I set City list_filter
as below:
@admin.register(City)
class CityAdmin(admin.ModelAdmin):
list_display = ('id', 'name')
list_filter = ('country__name',)
which show all countries in right menu.
So, is there a way to show list of countries in a dropdown menu instead of showing them as a list?
Thanks
In the standard django-admin i don’t know a way of achieving this.
I use jazzmin on my projects, it has this feature builtin. It’s a great project, and it’s beautiful. In their docs there’s a link to a live preview.
Hi, thank you for your answer!
I forgot to specify that I would not like to use third-parties libraries
Oh, i see.
Looking into the django source code, i think that you need to:
- Create a filter class that inherits from
django.contrib.admin.filters.SimpleListFilter
;
- override the
template_name
to your template;
- Use the created filter on your admin class;
The default template that django uses is at: django/contrib/admin/templates/admin/filter.html
. It’s contents are below:
{% load i18n %}
<details data-filter-title="{{ title }}" open>
<summary>
{% blocktranslate with filter_title=title %} By {{ filter_title }} {% endblocktranslate %}
</summary>
<ul>
{% for choice in choices %}
<li{% if choice.selected %} class="selected"{% endif %}>
<a href="{{ choice.query_string|iriencode }}">{{ choice.display }}</a></li>
{% endfor %}
</ul>
</details>
So instead of creating a <ul>
and <li>
for each option, you may create a <select>
and give it the option
for each option.
Hope you suceed!
I took inspiration from this link and it works!
This is my filter template put in <APP_NAME>/<MODEL_NAME>/filter.html
:
{% load i18n %}
<script type="text/javascript">var go_from_select = function(opt) { window.location = window.location.pathname + opt };</script>
<h3>{% blocktrans with title as filter_title %} By {{ filter_title }} {% endblocktrans %}</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>
I hope it will be useful for someone!
1 Like