Django Stale模型对象和窗体ChoiceField与ModelChoiceField [英] Django Stale Model Objects and Forms ChoiceField vs ModelChoiceField
问题描述
这只是一个奇怪的错误。我创建了一个Form类来处理数据库中的文档选择。当然,必须从数据库获取文档列表来填充可用选项。我通过手动构建选项并使用ChoiceField获得陈旧行为。但是,当使用ModelChoiceField选项queryset时,我得到准确的结果。
This is just a curiosity that bugs me. I created a Form class to handle document selection from a database. Naturally, one must get the list of documents from the database to populate the available choices. I get "stale" behavior from building the choices manually and using a ChoiceField. But I get the accurate result when utilizing the ModelChoiceField option "queryset".
陈旧我的意思是,如果我上传一个新的文档并呈现页面,列表显示只有旧的一组文件(有时甚至在刷新页面后仍然存在,根据视图逻辑应该重新生成表单 - 这是第二种方法按预期工作,无论用例如何)。
示例如下:
By "stale" I mean if I upload a new document and render the page, the list shows only the old set of documents (sometimes persisting even after refresh of the page, which according to the view logic should regenerate the form--proof of this is the fact that the second method works as expected no matter the use case). Example as follows:
陈旧版本:
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())
什么给了?有什么不同?为什么他们的行为不同?
What gives? What's the difference? Why do they behave differently?
推荐答案
陈旧的版本类体应该在
__ init __
方法! - mariodev
the stale version class body should be inside
__init__
method! – mariodev
谢谢mariodev。
Thank you mariodev.
能够生成正常运行的代码。我的第一个尝试仍然无法正常工作:
Following this lead, I was able to generate code that functioned properly. My first attempt still failed to work properly:
class GetDocumentForm(forms.Form):
def __init__(self):
...
self.base_fields['document'].choices = self.document_choices[:]
这将允许我创建一个表单,但是当我尝试渲染时:
This would allow me to create a form, but when I attempted to render:
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:自定义表单重载 init 。你需要超级类。
The solution is here: StackOverflow -- Django: Overloading init for Custom Forms. You need the super class.
最后的工作代码:
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())
更加简洁。但是关键是要了解如何让它在两种方式工作。
Clearly using ModelChoiceField(queryset=Document.objects.all())
is much more succinct. But the point was to understand how to get it to work both ways.
干杯。
这篇关于Django Stale模型对象和窗体ChoiceField与ModelChoiceField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!