【发布时间】:2011-07-22 16:55:15
【问题描述】:
如果对于您要过滤的字段,您有超过 10 个值,则过滤侧边栏开始变得丑陋且难以使用。
我正在寻找一种解决方案,将<li> 替换为下拉选择(组合框)或类似的东西来解决相同的问题。
【问题讨论】:
-
你看过 django-grappelli 吗?看起来正是你想要的,所以你可以看看它是如何完成的。
标签: django django-admin
如果对于您要过滤的字段,您有超过 10 个值,则过滤侧边栏开始变得丑陋且难以使用。
我正在寻找一种解决方案,将<li> 替换为下拉选择(组合框)或类似的东西来解决相同的问题。
【问题讨论】:
标签: django django-admin
几周前我也在为同样的问题苦苦挣扎。所以这个答案可能对未来的一些开发人员有用。
我设法通过编写自定义 template.html
解决了这个问题
我已经将代码捆绑在一个很棒的包中,现在它对你也一样,here's the link。
1.安装:
pip install django-admin-searchable-dropdown
此命令将在您的项目中安装最新版本的软件包。
现在,通过将 admin_searchable_dropdown 添加到 INSTALLED_APPS 内的 settings.py 文件中,将包包含在您的项目中。
2。用法:
假设您有以下模型:
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)
并且您想在company 的基础上过滤CarModelAdmin 中的结果。您需要在CarCompany 中定义search_fields,然后像这样定义过滤器:
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]
# ...
执行这些步骤后,您可能会看到过滤器:
auto_complete 功能),所以只要您使用的 Django 版本大于 2.0,就可以了。list_filters,例如更改下拉菜单上方的标题或自定义搜索逻辑等。str(obj) 以外的其他内容
【讨论】:
我不喜欢目前提供的所有解决方案。
为什么?如果对于要过滤的字段,您有超过 10 个值,那么列表视图框也不是那么方便。我建议使用 django admin 的标准搜索字段功能,它会显示一个搜索字段:
class BooksAdmin(admin.ModelAdmin):
list_display = ('ISBN', 'title')
search_fields = ('ISBN',)
# instead of: list_filter = ('ISBN',)
ordering = ('title',)
【讨论】:
感谢@beholderrk、@gediminas 和@jk-laiho!我把它打包成reusable app。
安装:
pip install django-admin-list-filter-dropdown
在settings.py中启用:
INSTALLED_APPS = (
...
'django_admin_listfilter_dropdown',
...
)
在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),
)
它是这样的:
【讨论】:
能否举个完整的例子。它像以前一样显示。 这是我的代码
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),
)
【讨论】:
http://djangosuit.com/ 还提供列表过滤器的下拉菜单。
【讨论】:
最好的解决方案是在admin/filter.html 中创建一个新模板并实现@beholderrk 建议的HTML 代码。刚刚为客户实现了它,效果很好。
DropdownFilter and RelatedDropdownFilter 的问题是它失去了正确的显示。代替Charfield(choices=xxx) 的翻译字符串,它将显示True、False 等等。
【讨论】:
您可以将 django 安装中的管理模板复制到项目中的模板/管理文件夹中。
然后,您需要在要在其中显示输出的表单或模板中执行以下 2 项操作:
如果您正在使用表单,因为您希望将列表选项发布回数据库,您可以在您的 model.py 中,在您有选择的字段上,输入如下内容:
choice = forms.IntegerField(widget=forms.Select(choices=CHOICES))
如果只是在页面上显示,那么你会在模板标签上输出如下内容:
<select>
{% for choices in object.details.all %}
<option> {{ object.choice }} </option>
{% endfor %}
</select>
【讨论】:
一个简单的选择是使用django-grappelli,它将所有过滤器替换为下拉菜单。
【讨论】:
我无法评论答案,所以我会在这里添加到 beholderrk 的答案。
dropdown_filter.html 或类似名称的新模板dropdown_filter.html
在filters.py中创建一个新的过滤器类:
from django.contrib.admin.filters import AllValuesFieldListFilter
class DropdownFilter(AllValuesFieldListFilter):
template = 'admin/dropdown_filter.html'
现在你可以在你的管理类中使用这个过滤器了:
class SomeAdmin(admin.ModelAdmin):
# ...
list_filter = (('country', DropdownFilter),)
效果很好!
【讨论】:
RelatedFieldListFilter 继承,但相同的模板有效。
ChoicesFieldListFilter 继承带有 choices kwarg 的字段。使用 AllValuesFieldListFilter 确实有效,但它显示的是值而不是人类可读的名称。
使用来自 feincms 的 filter.html
{% 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>
【讨论】:
{% endif %} 和 </ul>)轻松返回到“全部”选项:@987654325 @。我发现“删除”链接比在下拉菜单中选择“全部”要少得多。