【问题标题】:simplest way to override Django admin inline to request formfield_for_dbfield for each instance覆盖 Django 管理内联以请求每个实例的 formfield_for_dbfield 的最简单方法
【发布时间】:2017-01-22 09:38:07
【问题描述】:

我想在 Django 管理内联中为相同类型的模型字段提供不同的小部件来输入表单字段。

我在我的商店应用程序中实现了实体-属性-值范式的一个版本(我尝试了 eav-django,但它不够灵活)。在我的模型中,它是 Product-Parameter-Value(参见下面的编辑)。 一切都按我的意愿工作,除了在为 Parameter-Value 对包含管理内联时,每个值都使用相同的输入表单域。我知道这是默认的 Django 管理行为,因为它对每个内联行使用相同的表单集。

我想使用我的参数回调(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()

【问题讨论】:

    标签: python django django-admin


    【解决方案1】:

    我最终解决这个问题的方法是使用 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 类。您几乎可以使用AdminRadioSelect(attrs={'class': 'radiolist'}) 修复RadioSelect,但没有CheckboxSelectMultiple 的管理员版本,所以我更喜欢一致性。 <fieldset> 包装元素中还缺少一个 aligned 类。

    看来我得忍受这个了!

    【讨论】:

      猜你喜欢
      • 2020-08-12
      • 2012-09-05
      • 1970-01-01
      • 2010-10-15
      • 2019-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多