2017-10-04 81 views
0

假设我有两个模型,GroupPerson,其中GroupPerson的外键字段。在管理页面中,组被表示为人员管理的下拉/选择字段。现在,我希望选择的数量被限制为5个,并且应该根据它们的name进行排序。如何限制Django中的选择数admin

目前,我有以下代码:

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.

我搜索了那个错误,发现很多SO线程,但他们没有一个似乎帮助我处理我的情况。

以下是完整的堆栈跟踪:

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. 
+0

请显示完整的回溯。 – Alasdair

+0

@Alasdair描述更新。 –

回答

1

您可以修改查询集内初始化方法,发现前五组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__' 
+0

如果你有一个自定义窗体类(例如'form = PersonAdminForm'),这也可以吗? –

+0

发表你的自定义表单类,我猜你会直接找到'group'字段作为'form.group.queryset',尽管'form.base_fields ['group']'字典 – Satendra

+0

对不起,查询中的错误,你指定实际上是我所拥有的。 –

1

为了避免有关筛选切片查询集的错误,可能需要先获取前五个组,然后使用__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

相关问题