【问题标题】:Django Stale Model Objects and Forms ChoiceField vs ModelChoiceFieldDjango 陈旧模型对象和表单 ChoiceField 与 ModelChoiceField
【发布时间】:2013-09-06 02:25:37
【问题描述】:

这只是困扰我的好奇心。我创建了一个 Form 类来处理从数据库中选择的文档。自然,必须从数据库中获取文档列表以填充可用选项。通过手动构建选择并使用 ChoiceField,我得到了“陈旧”的行为。但是当使用 ModelChoiceField 选项“queryset”时,我得到了准确的结果。

“陈旧”是指如果我上传新文档并呈现页面,列表仅显示旧文档集(有时即使在刷新页面后仍然存在,根据视图逻辑应该重新生成表单 - -证明这一点的事实是,无论用例如何,第二种方法都按预期工作)。 示例如下:

旧版本:

class GetDocumentForm(forms.Form):
    document_query   = Document.objects.all().order_by('docfile')
    document_choices = []

    for document in document_query:
        document_choices.append((document.id, document.docfile.name))

    document         = forms.ChoiceField(label='', choices=document_choices)

准确版:

class GetDocumentForm(forms.Form):
    document         = forms.ModelChoiceField(queryset=Document.objects.all())

什么给了?有什么不同?为什么它们的行为不同?

【问题讨论】:

  • 陈旧版本的类主体应该在__init__方法内!

标签: django django-forms


【解决方案1】:

旧版本的类主体应该在__init__ 方法中! – 马里奥德夫

谢谢 mariodev。

按照这个引导,我能够生成运行正常的代码。我的第一次尝试仍然无法正常工作:

class GetDocumentForm(forms.Form):
    def __init__(self):
        ...
        self.base_fields['document'].choices = self.document_choices[:]

这将允许我创建一个表单,但是当我尝试渲染时:

In [1]: from WebSite.forms import *

In [2]: doc_form = GetDocumentForm()

In [3]: print doc_form.as_p()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

AttributeError: 'GetDocumentForm' object has no attribute '_errors'

解决方案在这里:StackOverflow -- Django: Overloading init for Custom Forms。你需要超类。

最终的工作代码:

class GetDocumentForm(forms.Form):
    document          = forms.ChoiceField()

    def __init__(self, *args, **kwargs):
        super(GetDocumentForm, self).__init__(*args, **kwargs)

        for doc in Document.objects.all().order_by('docfile'):
            self.fields['document'].choices.append((doc.id, doc.docfile.name))

显然使用ModelChoiceField(queryset=Document.objects.all()) 更简洁。但关键是要了解如何让它双向发挥作用。

干杯。

【讨论】:

  • 很高兴我能帮上忙。此外,由于您正在访问相关字段doc.docfile.name,因此您需要在查询中使用select_related(),以避免多个数据库命中。
  • 再次感谢。另一个有用的建议。 :)
猜你喜欢
  • 2018-02-05
  • 1970-01-01
  • 2019-04-04
  • 2011-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-08
  • 2021-01-06
相关资源
最近更新 更多