Alb*_*ony 7 django django-models
假设如果有一个名为“城市”的模型,并且在管理端有一个过滤器“city_name”来根据城市名称过滤模型。默认情况下,django 只允许从 django admin 过滤器中选择一个城市名称。但我需要在 django admin 过滤器中选择多个城市名称。我该怎么做??
您可以使用内置AllValuesFieldListFilter的稍微修改版本:
from django.contrib import admin
from django.contrib.admin.utils import reverse_field_path
from django.utils.translation import gettext_lazy as _
class MultiSelectFieldListFilter(admin.FieldListFilter):
def __init__(self, field, request, params, model, model_admin, field_path):
self.lookup_kwarg = field_path + '__in'
self.lookup_kwarg_isnull = field_path + '__isnull'
super().__init__(field, request, params, model, model_admin, field_path)
self.lookup_val = self.used_parameters.get(self.lookup_kwarg, [])
if len(self.lookup_val) == 1 and self.lookup_val[0] == '':
self.lookup_val = []
self.lookup_val_isnull = self.used_parameters.get(self.lookup_kwarg_isnull)
self.empty_value_display = model_admin.get_empty_value_display()
parent_model, reverse_path = reverse_field_path(model, field_path)
# Obey parent ModelAdmin queryset when deciding which options to show
if model == parent_model:
queryset = model_admin.get_queryset(request)
else:
queryset = parent_model._default_manager.all()
self.lookup_choices = queryset.distinct().order_by(field.name).values_list(field.name, flat=True)
def expected_parameters(self):
return [self.lookup_kwarg, self.lookup_kwarg_isnull]
def choices(self, changelist):
yield {
'selected': not self.lookup_val and self.lookup_val_isnull is None,
'query_string': changelist.get_query_string(remove=[self.lookup_kwarg, self.lookup_kwarg_isnull]),
'display': _('All'),
}
include_none = False
for val in self.lookup_choices:
if val is None:
include_none = True
continue
val = str(val)
if val in self.lookup_val:
values = [v for v in self.lookup_val if v != val]
else:
values = self.lookup_val + [ val ]
if values:
yield {
'selected': val in self.lookup_val,
'query_string': changelist.get_query_string({self.lookup_kwarg: ','.join(values)}, [self.lookup_kwarg_isnull]),
'display': val,
}
else:
yield {
'selected': val in self.lookup_val,
'query_string': changelist.get_query_string(remove=[self.lookup_kwarg]),
'display': val,
}
if include_none:
yield {
'selected': bool(self.lookup_val_isnull),
'query_string': changelist.get_query_string({self.lookup_kwarg_isnull: 'True'}, [self.lookup_kwarg]),
'display': self.empty_value_display,
}
Run Code Online (Sandbox Code Playgroud)
值中的转义逗号也应该实现,但我不需要它。
(使用 Django 2.2.5 测试)
小智 1
您可以通过继承来使用Django自定义list_filterdjango.contrib.admin.SimpleListFilter
这是一个简单的例子:
from django.contrib import admin
class MultiSelectFilter(admin.SimpleListFilter):
# Filter title
title = 'Cities'
# model field
parameter_name = 'city_name'
def lookups(self, request, model_admin):
# you can modify this part, this is less DRY approach.
# P.S. assuming city_name is lowercase CharField
return (
('city1,city2,city3', 'City1 or City2 or City3'),
('city4,city5,city6', 'City3 or City4 or City6'),
)
def queryset(self, request, queryset):
if self.value() in ('city1,city2,city3', 'city4,city5,city6'):
# filter if a choice selected
return queryset.filter(city_name__in=self.value().split(','))
# default for no filtering
return queryset
Run Code Online (Sandbox Code Playgroud)
您可以在此处参考文档
| 归档时间: |
|
| 查看次数: |
12336 次 |
| 最近记录: |