假设我有两个模型,Group
和Person
,其中Group
是Person
的外键字段。在管理页面中,Group表示为Person admin的下拉/选择字段。现在,我希望选择的数量限制在,比如说五个,并且应该根据它们的name
来排序。
目前,我有以下代码:
class PersonAdmin(admin.ModelAdmin):
form = PersonAdminForm
...
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
if db_field.name == 'group':
kwargs['queryset'] = Group.objects.all().order_by('name')[:5]
return super(PersonAdmin, self).formfield_for_foreignkey(
db_field, request, **kwargs)
class PersonAdminForm(forms.ModelForm):
class Meta:
model = Person
问题是,当我试图保存对象时,我会得到以下错误:AssertionError: Cannot filter a query once a slice has been taken.
。
我搜索了这个错误,发现了很多这样的线程,但它们似乎都没有对我的情况有所帮助。
下面是完整的堆栈跟踪:
Traceback (most recent call last):
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 111, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 583, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/utils/decorators.py", line 105, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/views/decorators/cache.py", line 52, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 206, in inner
return view(request, *args, **kwargs)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 1453, in add_view
return self.changeform_view(request, None, form_url, extra_context)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/utils/decorators.py", line 29, in _wrapper
return bound_func(*args, **kwargs)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/utils/decorators.py", line 105, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/utils/decorators.py", line 25, in bound_func
return func.__get__(self, type(self))(*args2, **kwargs2)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/db/transaction.py", line 394, in inner
return func(*args, **kwargs)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 1396, in changeform_view
if form.is_valid():
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/forms/forms.py", line 162, in is_valid
return self.is_bound and not bool(self.errors)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/forms/forms.py", line 154, in errors
self.full_clean()
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/forms/forms.py", line 353, in full_clean
self._clean_fields()
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/forms/forms.py", line 368, in _clean_fields
value = field.clean(value)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/forms/fields.py", line 150, in clean
value = self.to_python(value)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/forms/models.py", line 1185, in to_python
value = self.queryset.get(**{key: value})
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/db/models/query.py", line 345, in get
clone = self.filter(*args, **kwargs)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/db/models/query.py", line 691, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/home/man/.virtualenvs/foo/local/lib/python2.7/site-packages/django/db/models/query.py", line 703, in _filter_or_exclude
"Cannot filter a query once a slice has been taken."
AssertionError: Cannot filter a query once a slice has been taken.
发布于 2017-10-04 12:21:40
您可以在init方法中修改queryset,找到前五个组ids
,然后通过__in
查找在pk
上进行筛选。
class PersonAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(PersonAdminForm, self).__init__(*args, **kwargs)
group_ids = Group.objects.all().order_by('name').values_list('pk', flat=True)[:5]
self.fields['group'].queryset = Group.objects.filter(pk__in=group_ids).order_by('name')
group = forms.ModelChoiceField(queryset=None, empty_label=None)
class Meta:
model = Person
fields = '__all__'
发布于 2017-10-04 14:20:56
为了避免过滤切片查询集的错误,您可能需要获取前五个组,然后使用__in
查找创建第二个查询集。很讨厌,但我认为它会成功的。
first_five = list(Group.objects.all().order_by('name')[:5].values('pk', flat=True))
queryset = Group.objects.filter(id__in=first_five).order_by('name')[:5]
如果您已经有了一个自定义模型表单,那么我认为这段代码最干净的地方应该是表单的__init__
方法,而不是重写formfield_for_foreignkey
。
https://stackoverflow.com/questions/46564705
复制相似问题