Django Admin 中的动态字段
我想要关于一个字段的值的其他字段。因此,我构建了一个自定义管理表单来添加一些新字段。
与 jacobian 1 的博客文章相关,这就是我想到的with:
class ProductAdminForm(forms.ModelForm):
class Meta:
model = Product
def __init__(self, *args, **kwargs):
super(ProductAdminForm, self).__init__(*args, **kwargs)
self.fields['foo'] = forms.IntegerField(label="foo")
class ProductAdmin(admin.ModelAdmin):
form = ProductAdminForm
admin.site.register(Product, ProductAdmin)
但是附加字段“foo”没有显示在管理中。如果我像这样添加字段,一切都可以正常工作,但不那么动态,以添加有关模型的另一个字段的值的字段
class ProductAdminForm(forms.ModelForm):
foo = forms.IntegerField(label="foo")
class Meta:
model = Product
class ProductAdmin(admin.ModelAdmin):
form = ProductAdminForm
admin.site.register(Product, ProductAdmin)
那么是否有任何初始化方法我必须再次触发才能使新字段工作?或者还有其他的尝试吗?
I want to have additional fields regarding value of one field. Therefor I build a custom admin form to add some new fields.
Related to the blogpost of jacobian 1 this is what I came up with:
class ProductAdminForm(forms.ModelForm):
class Meta:
model = Product
def __init__(self, *args, **kwargs):
super(ProductAdminForm, self).__init__(*args, **kwargs)
self.fields['foo'] = forms.IntegerField(label="foo")
class ProductAdmin(admin.ModelAdmin):
form = ProductAdminForm
admin.site.register(Product, ProductAdmin)
But the additional field 'foo' does not show up in the admin. If I add the field like this, all works fine but is not as dynamic as required, to add the fields regarding the value of another field of the model
class ProductAdminForm(forms.ModelForm):
foo = forms.IntegerField(label="foo")
class Meta:
model = Product
class ProductAdmin(admin.ModelAdmin):
form = ProductAdminForm
admin.site.register(Product, ProductAdmin)
So is there any initialize method that i have to trigger again to make the new field working? Or is there any other attempt?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
这是问题的解决方案。感谢 koniiiik,我尝试通过扩展 *get_fieldsets* 方法来解决这个问题。
如果您使用多个字段集,请务必使用适当的索引将其添加到正确的字段集。
Here is a solution to the problem. Thanks to koniiiik i tried to solve this by extending the *get_fieldsets* method
If you use multiple fieldsets be sure to add the to the right fieldset by using the appropriate index.
上面接受的答案适用于旧版本的 django,这就是我的做法。现在这个问题在后来的 django 版本中已经被打破了(我现在使用的是 1.68,但现在已经很旧了)。
它现在被破坏的原因是因为从
ModelAdmin.get_fieldsets()
返回的字段集中的任何字段最终都会作为fields=parameter
传递到modelform_factory()< /code>,这会给你一个错误,因为列表中的字段不存在(并且在实例化你的表单并调用它的
__init__
之前不会存在)。为了解决这个问题,我们必须重写 ModelAdmin.get_form() 并提供不包含稍后添加的任何额外字段的字段列表。
get_form
的默认行为是调用get_fieldsets()
来获取此信息,我们必须防止这种情况发生:The accepted answer above worked in older versions of django, and that's how I was doing it. This has now broken in later django versions (I am on 1.68 at the moment, but even that is old now).
The reason it is now broken is because any fields within fieldsets you return from
ModelAdmin.get_fieldsets()
are ultimately passed as thefields=parameter
tomodelform_factory()
, which will give you an error because the fields on your list do not exist (and will not exist until your form is instantiated and its__init__
is called).In order to fix this, we must override
ModelAdmin.get_form()
and supply a list of fields that does not include any extra fields that will be added later. The default behavior ofget_form
is to callget_fieldsets()
for this information, and we must prevent that from happening:也许我有点晚了...但是,我正在使用 Django 3.0,并且还想根据请求动态地将一些自定义字段添加到表单中。
我最终得到了一个类似于@tehfink 结合@little_birdie 描述的解决方案。
但是,仅按照建议更新 self.form.declared_fields 并没有帮助。此过程的结果是,
self.form.declared_fields
中定义的自定义字段列表始终随着请求的不同而增长。我通过首先初始化这个字典来解决这个问题:
其中
custom_attribute.field
是一个表单字段实例。此外,还需要定义一个 ModelForm,其中在初始化期间也动态添加了自定义字段:
并在 ModelAdmin 中使用此 ModelForm。
之后,新定义的属性可以在例如字段集中使用。
Maybe I am a bit late... However, I am using Django 3.0 and also wanted to dynamically ad some custom fields to the form, depending on the request.
I end up with a solution similar to the one described by @tehfink combined with @little_birdie.
However, just updating
self.form.declared_fields
as suggested didn't help. The result of this procedure is, that the list of custom fields defined inself.form.declared_fields
always grows from request to request.I solved this by initialising this dictionary first:
where
custom_attribute.field
is a form field instance.Additionally, it was required to define a ModelForm, wherein during initialisation the custom fields have been added dynamically as well:
and use this ModelForm in the ModelAdmin.
Afterwards, the newly defined attributes can be used in, e.g., a fieldset.
这适用于在 Django 1.9.3 中添加动态字段,仅使用 ModelAdmin 类(无 ModelForm)并覆盖
get_fields
。我还不知道它有多强大:This works for adding dynamic fields in Django 1.9.3, using just a ModelAdmin class (no ModelForm) and by overriding
get_fields
. I don't know yet how robust it is:虽然 Jacob 的帖子可能适用于常规的 ModelForm(尽管它已经存在一年半多了),但管理却有些不同。
所有定义模型、形成 ModelAdmins 等的声明性方式都大量使用了元类和类内省。与管理员相同 - 当您告诉
ModelAdmin
使用特定表单而不是创建默认表单时,它会内省类。它从类本身获取字段列表和其他内容,而不实例化它。然而,您的自定义类并未在类级别定义额外的表单字段,而是在实例化后动态添加一个表单字段 - 这对于
ModelAdmin
来说已经来不及识别了这个变化。解决问题的一种方法可能是子类
ModelAdmin
并重写其get_fieldsets
方法以实际实例化ModelForm
类并获取字段列表来自实例而不是类。不过,您必须记住,这可能比默认实现要慢一些。While Jacob's post might work all right for regular
ModelForm
s (even though it's more than a year and a half old), the admin is a somewhat different matter.All the declarative way of defining models, forms ModelAdmins and whatnot makes heavy use of metaclasses and class introspection. Same with the admin – when you tell a
ModelAdmin
to use a specific form istead of creating a default one, it introspects the class. It gets the list of fields and other stuff from the class itself without instantiating it.Your custom class, however, does not define the extra form field at class level, instead it dynamically adds one after it has been instantiated – that's too late for the
ModelAdmin
to recognize this change.One way to go about your problem might be to subclass
ModelAdmin
and override itsget_fieldsets
method to actually instantiate theModelForm
class and get the list of fields from the instance instead of the class. You'll have to keep in mind, though, that this might be somewhat slower than the default implementation.您可以使用表单元类创建动态字段和字段集。下面给出示例代码。根据您的要求添加循环逻辑。
You can create dynamic fields and fieldset using the form meta class. Sample code is given below. Add the loop logic as per you requirements.
Stephan 的回答很优雅,但是当我在 dj1.6 中使用时,它要求该字段是一个元组。
完整的解决方案如下所示:
Stephan's answer is elegant, but when I used in in dj1.6 it required the field to be a tuple.
The complete solution looked like this:
不确定为什么这不起作用,但可能的解决方法是静态定义字段(在表单上),然后在 __init__ 中覆盖它?
not sure why that's not working, but could a possible workaround be to define the field statically (on the form) and then override it in the
__init__
?我很长一段时间都无法解决动态添加字段的问题。
解决方案“little_birdie”确实有效。谢谢小鸟))
唯一的细微差别是:
“Self.declared_fieldsets”应替换为“self.fieldsets”。
我用的是1.10版本。也许有些事情已经改变了。
如果有人找到更简单、更优雅的解决方案,请在此处展示。
感谢大家)))
I for a long time could not solve a problem with dynamic addition of fields.
The solution "little_birdie" really works. Thank you Birdie))
The only nuance is:
"Self.declared_fieldsets" should be replaced with "self.fieldsets".
I used version 1.10. Perhaps something has changed.
If someone finds an even simpler and elegant solution, show here.
Thanks to all )))