【问题标题】:Django form with ModelMultipleChoiceField rendered empty带有 ModelMultipleChoiceField 的 Django 表单呈现为空
【发布时间】:2018-09-26 15:56:41
【问题描述】:

我在设置带有ModelMultipleChoiceField 的表单时遇到问题,其中查询集取决于用户。我的目标是实现导出功能。

我的观点是这样的:

class ExportView(FormView):
    template_name = 'ExportTemplate.html'

    def get(self, request, *args, **kwargs):
        self.form_class = ExportForm(user = request.user)
        return render(request, self.template_name, {'form': self.form_class})

    def get_success_url(self):
        return '/addrbook/'

    def form_valid(self, form):
        # This method is called when valid form data has been POSTed.
        # It should return an HttpResponse.
        return super().form_valid(form)

表格:

class ExportForm(forms.Form):
    def __init__(self, user, *args, **kwargs):
        usersContacts = ContactManager().getAllUsersContacts()
        self.contactList = forms.ModelMultipleChoiceField(queryset = usersContacts[str(user)])
        print(usersContacts[str(user)])
        super(ExportForm, self).__init__(*args, **kwargs)

我验证了查询集不为空,它包含一个模型对象列表。

我的模板如下所示:

<form method="post">{% csrf_token %}
{{ form }}
<input type="submit">
</form>

唯一呈现的是提交按钮。

让我完全不确定python基础的另一件事是这段代码:

class ExportForm(forms.Form):
    contactList = forms.ModelMultipleChoiceField(queryset = [])

    def __init__(self, user, *args, **kwargs):
        usersContacts = ContactManager().getAllUsersContacts()
        self.contactList.queryset = usersContacts[str(user)]
        print(usersContacts[str(user)])
        super(ExportForm, self).__init__(*args, **kwargs)

返回运行时错误:

'ExportForm' object has no attribute 'contactList' 

这怎么可能? contactList 成员是 ExportForm 类定义的一部分,“self”应指向该类的对象。

有人可以向我解释为什么表单字段显示为空和/或向我指出将用户传递给表单的更好方法吗?

编辑:这是我对答案所做的更改以使其正常工作,尽管我现在偶然发现了一个不同的问题(该字段需要一个查询集,而不是模型对象列表):

查看:

class ExportView(FormView):
template_name = 'ExportTemplate.html'
form_class = ExportForm

def get_form_kwargs(self):
    kwargs = super(ExportView, self).get_form_kwargs()
    kwargs['user'] = self.request.user
    return kwargs

表格:

class ExportForm(forms.Form):
contactList = forms.ModelMultipleChoiceField(queryset = Contact.objects.none())

def __init__(self, *args, **kwargs):
    user = kwargs['user']
    kwargs.pop('user', None)
    super(ExportForm, self).__init__(*args, **kwargs)
    usersContacts = ContactManager().getAllUsersContacts()
    self.fields['contactList'].queryset = usersContacts[str(user)]
    print(self.fields['contactList'].queryset)

【问题讨论】:

  • 使用self.contactList 时会出现属性错误,因为forms.Form 使用将字段存储在base_fields 字典中的元类。但正如我在下面的回答中所说,您应该使用 self.fields 来编辑单个表单实例的字段。

标签: python django


【解决方案1】:

首先,您应该在每次实例化时将user 传递给表单,而不仅仅是在get 方法中。使用FormView 执行此操作的方法是覆盖get_form_kwargs

def get_form_kwargs(self):
    kwargs = super(ExportForm, self).get_form_kwargs()
    kwargs[user] = self.request.user
    return kwargs

然后您可以删除您的 get() 方法。

然后,在您的表单类中,您应该使用none() 方法而不是空列表来获取空查询集。在__init__ 方法中,您可以从kwargs 弹出用户,然后在编辑字段之前调用super()。您通过self.fields 而不是self.contactList 编辑contactList 字段。请注意,Django 中字段名称的推荐样式是 contact_list 而不是 contactList

class ExportForm(forms.Form):
    contactList = forms.ModelMultipleChoiceField(queryset=YourModel.objects.none())

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super(ExportForm, self).__init__(*args, **kwargs)
        usersContacts = ContactManager().getAllUsersContacts()
        self.fields['contactList'].queryset = usersContacts[str(user)]

您没有显示ContactManager() 代码,但使用str(user) 作为字典键看起来很脆弱。改用user.pkuser.username 可能会更好。

【讨论】:

  • 感谢您指出这么多问题 :) 我将实施这些更改,看看效果如何
  • 'self.form_class' 不是实例化的表单吗?它被定义为 ExportForm(user = request.user)
  • 是的,我的错,它是实例化的形式。也许form 是一个实例化表单的更好名称,而不是form_class ;)
  • 是的,我从我在 SO 上找到的答案中复制了它
  • 谢谢,问题解决了,但现在我需要将集合作为查询集。可能会有点复杂,因为联系人是与单个用户和用户所在的组共享的
猜你喜欢
  • 2017-09-11
  • 2011-07-19
  • 1970-01-01
  • 2017-10-09
  • 2010-09-20
  • 2020-03-03
  • 1970-01-01
  • 1970-01-01
  • 2012-04-01
相关资源
最近更新 更多