2011-02-08 55 views
0

这里是我一直在挣扎了一天......限制Django的ModelChoiceField查询集到选定的项目

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

然后有一个用于撰写消息的表单。由于有成千上万的用户,因此在表单中的多选部件中显示选项并不方便,这是缺省行为。相反,使用FcbkComplete jquery插件,我使收件人字段看起来像用户输入收件人的输入字段,它很有用。

但是......

虽然窗体页上不可见,所有的用户列表呈现在页面中选择栏,这是我不希望的原因很明显。

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

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

回答

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) 
    ... 
1

你见过django-ajax-selects?我从来没有使用它,但它是在我的心理抢袋,当我遇到了一个问题,如听起来像你想解决的问题...

+0

看起来很有趣,很高兴看到一个工作演示。 – omat 2011-02-08 22:09:23

1

我会尝试两种方式之一!这可能是坏的,我真的只是想出来大声这里):

  1. 设置字段的查询集为空(查询集= Model.objects.none()),并具有jQuery的工具使用了Ajax的看法选择/搜索用户。使用clean_field函数手动验证用户是否有效。

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

我不确定的一件事是#2是否仍然会打到数据库,拉出5k +对象,只是不显示它们在HTML中。我不认为它应该,但是......不确定,根本!

+0

for 1,在clean_field()之前调用clean()并引发一个`invalid option`异常。 'clean'也应该被覆盖,但它是一个选项。对于2,我不想混淆模板,因为我有站点范围的字段和表单模板。但这也是一个选项。我仍然觉得应该有一个更清洁,更少哈克,更djangoish的方式。谢谢。 – omat 2011-02-08 23:26:58

+0

您的问题的唯一可能的解决方案(假设查询集过滤器不足)涉及不得不使用javascript和ajax视图。在我看来,这已经非常不错 - 你只能指望django是自我一致的,它不能满足使用javascript的所有可能性。我想我会在调用super()之前重写clean()方法使其工作:/ mmm hacky的确如此! – user608133 2011-02-08 23:49:57

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')