覆盖Django admin inline以便为每个实例

时间:2016-09-14 14:20:42

标签: python django django-admin

我想提供不同的小部件来为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()

1 个答案:

答案 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

使用这样的标准表单,带有选项的小部件(例如RadioSelectCheckboxSelectMultiple)在管理界面旁边会有列表项目符号,因为<ul>没有radiolist课程。您几乎可以使用RadioSelect修复AdminRadioSelect(attrs={'class': 'radiolist'}),但不存在CheckboxSelectMultiple的管理员版本,因此我更喜欢一致性。此外,aligned包装器元素中缺少<fieldset>个类。

看起来我不得不忍受这个!