0

这是我挣扎了一天的事情......

我有一个消息模型,其中一个recipients模型。ManyToManyFieldUser

然后有一个用于编写消息的表单。由于有成千上万的用户,因此在表单中的多选小部件中显示选项并不方便,这是默认行为。相反,使用 FcbkComplete jquery 插件,我使收件人字段看起来像一个输入字段,用户在其中键入收件人,并且它可以工作。

但...

尽管在表单页面上不可见,但所有用户列表都呈现在选择字段中的页面中,这是我不想要的,原因很明显。

我尝试覆盖 ModelChoiceField 的操作验证和查询集的行为,我使用了 MultipleChoice 小部件等。但它们都没有工作并且感觉自然。

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

4

4 回答 4

1

你见过django-ajax-selects吗?我从来没有用过它,但是当我遇到一个听起来像你试图解决的问题时,它就在我的精神抓包里……

于 2011-02-08T21:44:30.370 回答
1

我会尝试两种方法中的一种(这两种方法都可能不好!我真的只是在这里大声思考):

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

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

我不确定的一件事是#2 是否仍会访问数据库,提取 5k+ 个对象,只是不在 html 中显示它们。我认为不应该,但是……完全不确定!

于 2011-02-08T22:18:21.140 回答
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)
    ...
于 2011-02-11T20:34:23.410 回答
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')
于 2011-02-08T22:41:30.450 回答