这只是一种让我烦恼的好奇心。我创建了一个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())
是什么给出的?有什么不同?他们为什么表现不同?
答案 0 :(得分:3)
过时的版本类体应该在
__init__
方法内! - mariodev
谢谢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())
更加简洁。但关键是要了解如何让它以两种方式运作。
干杯。