Django Stale模型对象和窗体ChoiceField与ModelChoiceField [英] Django Stale Model Objects and Forms ChoiceField vs ModelChoiceField

查看:190
本文介绍了Django Stale模型对象和窗体ChoiceField与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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆