字段和基本字段 - Django
创建平面页面时,我希望用户从预定义列表中选择模板。为了保持 Flatpage
模型不变,我更喜欢 ChoiceField
而不是 ModelChoiceField
(后者提供模板的 PK,但我需要名称对于 template_name 字段):
class NewFlatpageForm(FlatpageForm):
template_name = forms.ChoiceField(choices = [])
def __init__(self, *args, **kwargs):
self.base_fields['template_name'].choices = ProjectTemplate.objects.values_list('path', 'name')
super(NewFlatpageForm, self).__init__(*args, **kwargs)
我覆盖 __init__
或 Django 在服务器启动时填充选择,然后不会更新列表。
我没有任何管理经验,但在不使用管理时,我使用 fields
属性做了类似的事情。然而在这种情况下,我得到一个异常,告诉 fields
不是表单的属性。 __dict__
向我展示了一个 base_fields
属性,并且使用它是有效的。那么,为什么在这里使用 base_fields ,为什么 fields
不存在,最后我是在做一些黑客行为吗?
When creating a flatpage, I want the user to select a template from a predefined list. In order to keep the Flatpage
model untouched, I prefer ChoiceField
over ModelChoiceField
(the latter provides the PK of the template, but I need the name for the template_name field):
class NewFlatpageForm(FlatpageForm):
template_name = forms.ChoiceField(choices = [])
def __init__(self, *args, **kwargs):
self.base_fields['template_name'].choices = ProjectTemplate.objects.values_list('path', 'name')
super(NewFlatpageForm, self).__init__(*args, **kwargs)
I override __init__
or Django populates choices at server start and does not update the list then.
I don't have any admin experience, but I did similar things using the fields
attribute when not using admin. However in this case, I got an exception telling fields
is not an attribute of the form. __dict__
showed me there's a base_fields
attribute and using it works. So, why use base_fields here, and why is fields
not present and finally am I doing something hacky?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在您调用
super
之后之前,fields
并不存在。因此,只需交换行的顺序,使super
排在第一位。fields
doesn't exist until after you've calledsuper
. So just swap the order of the lines, so thatsuper
comes first.我自己的经验教训是:修改
base_fields
意味着您的修改将“永远”保留(直到 python 退出)。在您的情况下,这可能不是问题,因为您始终使用相同的字段名称,并且您将其值替换为 ProjectTemplate 中的分配...在我的情况下,我想要基于构造函数中的参数完全不同的字段。由于我的字段名称通常不同,因此每次实例化表单时,我都会添加新字段,但不会删除上次的字段。
通过尽早调用
super
(如此处所示),然后对self.fields
而不是self.base_fields
进行动态更改,我能够消除字段列表不断增长的问题。现在它完全有意义了,但我并不熟悉所有的语法细节,而是通过破解而不是首先尝试理解它。A lesson from my own experience: modifying
base_fields
means that your modifications stick around "forever" (until python exits). In your case, that's probably not a problem, as you are always using the same field name, and you are replacing its values with the assignment from ProjectTemplate...In my case, I wanted completely different fields based on parameters in the constructor. Since my field names were usually different, each time I instantiated a form, I added new fields but didn't eliminate the ones from the last time.
By calling
super
early (as indicated here) and then making my dynamic changes toself.fields
instead ofself.base_fields
, I was able to eliminate the problem of an ever growing list of fields. It makes perfect sense now, but I wasn't familiar with all of the syntax details and was hacking through instead of trying to understand it first.除了乔·杰姆斯卡。如果您确实需要根据请求更改表单,则可以使用深层复制来确保引用不会更改任何内容:
In addition to Joe Germuska. If you truly need to change the form based on the request, you can use a deepcopy to make sure nothing is changed by reference: