这是我一天苦苦挣扎的......
我有一个消息模型,其中recipients
是ManyToManyField
模型的User
。
然后有一个撰写邮件的表单。由于有数千个用户,在表单中的多选小部件中显示选项并不方便,这是默认行为。相反,使用FcbkComplete jquery插件,我使收件人字段看起来像用户输入收件人的输入字段,并且它工作。
但是...
虽然在表单页面上不可见,但是所有用户列表都会在选择字段中呈现到页面中,这是我不想要的原因。
我尝试重写ModelChoiceField操作验证和查询集的行为,我使用了MultipleChoice小部件,等等。但是没有一个工作并感觉很自然。
那么,避免在客户端使用整个选项列表,但仍然能够针对查询集进行验证的(最佳)方法是什么?
答案 0 :(得分:1)
你见过django-ajax-selects吗?我从来没有使用它,但是当我遇到一个类似于你试图解决的问题时,它就在我的心理抓斗中......
答案 1 :(得分:1)
我会尝试两种方式中的一种(两者都可能很糟糕!我真的只是在这里大声思考):
将字段的查询集设置为空(queryset = Model.objects.none())并使用jquery工具使用ajax视图来选择/搜索用户。使用clean_field函数手动验证用户是否有效。
这是我的首选:编辑模板不循环遍历字段的查询集 - 所以html在select标签内有0个选项。也就是说,不使用form.as_p()方法或任何东西。
我不确定的一件事是#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)
...