Django Admin中的自定义筛选器返回可疑操作
我正在尝试实现的新版本,使其与Django 1.4和1.5兼容 经过相当多的改进,下面的代码几乎可以正常工作,但Django向我返回了一个可疑的操作错误。我知道如何破解它,但我不想触及Django的核心。如果您有一些建议,欢迎提供: 这是我的过滤器:Django Admin中的自定义筛选器返回可疑操作,django,django-admin,django-filter,Django,Django Admin,Django Filter,我正在尝试实现的新版本,使其与Django 1.4和1.5兼容 经过相当多的改进,下面的代码几乎可以正常工作,但Django向我返回了一个可疑的操作错误。我知道如何破解它,但我不想触及Django的核心。如果您有一些建议,欢迎提供: 这是我的过滤器: class RelatedNullFilterSpec(FieldListFilter): def __init__(self, field, request, params, model, model_admin, field_path)
class RelatedNullFilterSpec(FieldListFilter):
def __init__(self, field, request, params, model, model_admin, field_path):
field_root, field_name = field_path.rsplit('__', 1)
self.lookup_title = field.verbose_name
self.title = self.lookup_title
self.null_lookup_kwarg = '%s__isnull' % field_root
self.null_lookup_val = request.GET.get(self.null_lookup_kwarg, None)
self.lookup_kwarg = '%s__exact' % (field_path)
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
if isinstance(field, models.fields.BooleanField):
self.lookup_choices = (
# (None, _('All')),
('1', _('Yes')),
('0', _('No')))
else:
self.lookup_choices = field.get_choices(include_blank=False)
super(RelatedNullFilterSpec, self).__init__(field, request, params, model, model_admin, field_path)
def expected_parameters(self):
return [self.lookup_kwarg, self.null_lookup_kwarg]
def choices(self, cl):
yield {'selected': self.lookup_val is None and self.null_lookup_val is None,
'query_string': cl.get_query_string({}, [self.lookup_kwarg,self.null_lookup_kwarg]),
'display': _('All')}
yield {'selected': self.lookup_val is None and self.null_lookup_val=="True",
'query_string': cl.get_query_string({self.null_lookup_kwarg:True},[self.lookup_kwarg]),
'display': _('Null')}
yield {'selected': self.lookup_val is None and self.null_lookup_val=="False",
'query_string': cl.get_query_string({self.null_lookup_kwarg:False},[self.lookup_kwarg]),
'display': _('Not Null')}
for pk_val, val in self.lookup_choices:
yield {'selected': self.lookup_val == smart_unicode(pk_val),
'query_string': cl.get_query_string({self.lookup_kwarg: pk_val},[self.null_lookup_kwarg]),
'display': val}
然后在我的管理中,我有以下内容:
list_filter = ('time_added', 'time_modified', ('model1__model2__property', RelatedNullFilterSpec),)
我总是从Django BaseModelAdmin类的lookup\u allowed
方法中得到这个错误
在django.db.models.options中,我可以实现一个hack来覆盖或扩展与自身相关的查找
,但这对我来说有点太hack了
编辑:请注意,以下几乎是标准的筛选器也返回相同的错误:('venture\uuu eat\uvenue',BooleanFieldListFilter)
一般来说,我的目标是希望有一个过滤器,允许我根据model2相关字段(Null/notnull)的存在/不存在以及属性的值(如果model2相关字段存在)对对象进行排序。这将是相当方便,我不认为太具体
最后,是的,当我没有为我的
model1\uuuu model2\uu属性请求此自定义筛选器时,一切都可以正常工作:-)当筛选器路径(元组的第一个元素)有双下划线时,这似乎是Django中的一个错误。。。在您的案例中,“model1\uuuuuModel2\uuuuuuuu属性”
注意:现在已在Django 1.7中修复
详情如下:
这很难看,但到目前为止,我找到的唯一解决方法是将此固定和重写的方法粘贴到ModelAdmin
中,您要在其中使用list\u过滤器
:
def lookup_allowed(self, lookup, value):
"""
Copy and pasted from ModelAdmin to fix bug in Django
https://code.djangoproject.com/ticket/19182
"""
from django.db.models.constants import LOOKUP_SEP
from django.db.models.sql.constants import QUERY_TERMS
from django.contrib.admin import FieldListFilter
from django.contrib.admin import widgets
model = self.model
# Check FKey lookups that are allowed, so that popups produced by
# ForeignKeyRawIdWidget, on the basis of ForeignKey.limit_choices_to,
# are allowed to work.
for l in model._meta.related_fkey_lookups:
for k, v in widgets.url_params_from_lookup_dict(l).items():
if k == lookup and v == value:
return True
parts = lookup.split(LOOKUP_SEP)
# Last term in lookup is a query term (__exact, __startswith etc)
# This term can be ignored.
if len(parts) > 1 and parts[-1] in QUERY_TERMS:
parts.pop()
# Special case -- foo__id__exact and foo__id queries are implied
# if foo has been specificially included in the lookup list; so
# drop __id if it is the last part. However, first we need to find
# the pk attribute name.
rel_name = None
for part in parts[:-1]:
try:
field, _, _, _ = model._meta.get_field_by_name(part)
except FieldDoesNotExist:
# Lookups on non-existants fields are ok, since they're ignored
# later.
return True
if hasattr(field, 'rel'):
model = field.rel.to
rel_name = field.rel.get_related_field().name
elif isinstance(field, RelatedObject):
model = field.model
rel_name = model._meta.pk.name
else:
rel_name = None
if rel_name and len(parts) > 1 and parts[-1] == rel_name:
parts.pop()
if len(parts) == 1:
return True
clean_lookup = LOOKUP_SEP.join(parts)
// FIX BEGINS:
valid_lookups = [self.date_hierarchy]
for filter_item in self.list_filter:
if callable(filter_item):
valid_lookups.append(filter_item.parameter_name)
elif isinstance(filter_item, (list, tuple)):
valid_lookups.append(filter_item[0])
else:
valid_lookups.append(filter_item)
return clean_lookup in valid_lookups