将Django ModelChoiceField查询集限制为所选项

时间:2011-02-08 21:24:44

标签: django django-forms validation manytomanyfield

这是我一天苦苦挣扎的......

我有一个消息模型,其中recipientsManyToManyField模型的User

然后有一个撰写邮件的表单。由于有数千个用户,在表单中的多选小部件中显示选项并不方便,这是默认行为。相反,使用FcbkComplete jquery插件,我使收件人字段看起来像用户输入收件人的输入字段,并且它工作。

但是...

虽然在表单页面上不可见,但是所有用户列表都会在选择字段中呈现到页面中,这是我不想要的原因。

我尝试重写ModelChoiceField操作验证和查询集的行为,我使用了MultipleChoice小部件,等等。但是没有一个工作并感觉很自然。

那么,避免在客户端使用整个选项列表,但仍然能够针对查询集进行验证的(最佳)方法是什么?

4 个答案:

答案 0 :(得分:1)

你见过django-ajax-selects吗?我从来没有使用它,但是当我遇到一个类似于你试图解决的问题时,它就在我的心理抓斗中......

答案 1 :(得分:1)

我会尝试两种方式中的一种(两者都可能很糟糕!我真的只是在这里大声思考):

  1. 将字段的查询集设置为空(queryset = Model.objects.none())并使用jquery工具使用ajax视图来选择/搜索用户。使用clean_field函数手动验证用户是否有效。

  2. 这是我的首选:编辑模板不循环遍历字段的查询集 - 所以html在select标签内有0个选项。也就是说,不使用form.as_p()方法或任何东西。

  3. 我不确定的一件事是#2是否仍然会攻击数据库,拔出5k +对象,而不是在html中显示它们。我认为不应该,但......根本不确定!

答案 2 :(得分:0)

如果您不关心建议,并且可以使用该ID,则Django Admin会为这些情况提供raw_id_field属性。

您还可以创建一个小部件,它使用用户名而不是ID并返回有效用户。以下几行:

# I haven't tested this code. It's just for illustration purposes
class RawUsernameField(forms.CharField):
  def clean(self, value):
    try:
      return User.objects.get(username=value)
    except User.DoesNotExist:
      rause forms.ValidationError(u'Invalid Username')

答案 3 :(得分:0)

我通过覆盖forms.ModelMultipleChoiceField的默认小部件来解决这个问题。新窗口小部件仅返回选定的字段,而不是整个选项列表:

class SelectMultipleUserWidget(forms.SelectMultiple):
    def render_options(self, choices, selected_choices):
        choices = [c for c in self.choices if str(c[0]) in selected_choices]
        self.choices = choices
        return super(SelectMultipleUserWidget, 
                     self).render_options([], selected_choices)

class ComposeForm(forms.Form):
    recipients = forms.ModelMultipleChoiceField(queryset=User.objects.all(),
                                                widget=SelectMultipleUserWidget)
    ...