我想提供不同的小部件来为Django admin内联中的相同类型的模型字段输入表单字段。
我已经在我的商店应用程序中实现了Entity-Attribute-Value范例的一个版本(我尝试了eav-django并且它不够灵活)。在我的模型中,它是Product-Parameter-Value(参见下面的编辑)。 一切都按我的意思工作,除了当包含一个参数值对的内联管理员时,每个值都使用相同的输入表单字段。我知道这是默认的Django管理员行为,因为它为每个内联行使用相同的formset。
我想在我的参数上使用回调(get_value_formfield)。我目前有:
class SpecificationValueAdminInline(admin.TabularInline):
model = SpecificationValue
fields = ('parameter', 'value')
readonly_fields = ('parameter',)
max_num = 0
def get_formset(self, request, instance, **kwargs):
"""Take a copy of the instance"""
self.parent_instance = instance
return super().get_formset(request, instance, **kwargs)
def formfield_for_dbfield(self, db_field, **kwargs):
"""Override admin function for requesting the formfield"""
if self.parent_instance and db_field.name == 'value':
# Notice first() on the end -->
sv_instance = SpecificationValue.objects.filter(
product=self.parent_instance).first()
formfield = sv_instance.parameter.get_value_formfield()
else:
formfield = super().formfield_for_dbfield(db_field, **kwargs)
return formfield
每个管理页面只调用一次formfield_for_dbfield。
如何覆盖默认行为,以便为每个SpecificationValue实例调用一次formfield_for_dbfield,最好每次都传递实例?
编辑:
以下是模型布局:
class Product(Model):
specification = ManyToManyField('SpecificationParameter',
through='SpecificationValue')
class SpecificationParameter(Model):
"""Other normal model fields here"""
type = models.PositiveSmallIntegerField(choices=TUPLE)
def get_value_formfield(self):
"""
Return the type of form field for parameter instance
with the correct widget for the value
"""
class SpecificationValue(Model):
product = ForeignKey(Product)
parameter = ForeignKey(SpecificationParameter)
# To store and retrieve all types of value, overrides CharField
value = CustomValueField()
答案 0 :(得分:0)
我最终解决此问题的方法是使用Admin Inline的form =
属性。这会跳过ModelAdmin的表单生成代码:
class SpecificationValueForm(ModelForm):
class Meta:
model = SpecificationValue
def __init__(self, instance=None, **kwargs):
super().__init__(instance=instance, **kwargs)
if instance:
self.fields['value'] = instance.parameter.get_value_formfield()
else:
self.fields['value'].disabled = True
class SpecificationValueAdminInline(admin.TabularInline):
form = SpecificationValueForm
使用这样的标准表单,带有选项的小部件(例如RadioSelect
和CheckboxSelectMultiple
)在管理界面旁边会有列表项目符号,因为<ul>
没有radiolist
课程。您几乎可以使用RadioSelect
修复AdminRadioSelect(attrs={'class': 'radiolist'})
,但不存在CheckboxSelectMultiple
的管理员版本,因此我更喜欢一致性。此外,aligned
包装器元素中缺少<fieldset>
个类。
看起来我不得不忍受这个!