代码之家  ›  专栏  ›  技术社区  ›  Jordan Reiter

如何防止Django Admin重写自定义字段的自定义小部件?

  •  0
  • Jordan Reiter  · 技术社区  · 6 年前

    我有一个模型字段、一个表单字段和一个小部件,我正在应用程序中使用。代码的细节无关紧要。关键是该字段在常规表单中正确呈现,但在管理中被重写。

    下面是该字段基本外观的一些伪代码:

    class SandwichWidget(forms.Widget):
        template_name = 'sandwichfield/widgets/sandwichfield.html'
    
        def __init__(self, attrs=None, date_format=None, time_format=None):
            widgets = (
                NumberInput(),
                Select(choices=FILLING_CHOICES),
                NumberInput(),
            )
            super(SandwichWidget, self).__init__(widgets, attrs)
    
        def decompress(self, value):
            if value:
                value = Sandwich(value)
                return [
                    value.top,
                    value.middle,
                    value.bottom
                ]
            return [None, None, None]
    
    
    class SandwichFormField(forms.MultiValueField):
        widget = SandwichWidget
    
        def __init__(self, input_date_formats=None, input_time_formats=None, *args, **kwargs):
            fields = (
                forms.IntegerField(),
                forms.CharField(),
                forms.IntegerField(),
            )
            super(SandwichFormField, self).__init__(fields, *args, **kwargs)
    
    
    class SandwichField(models.PositiveIntegerField):
    
        def get_internal_type(self):
            return 'IntegerField'
    
        def formfield(self, *args, **kwargs):
            defaults={'form_class': SandwichFormField}
            defaults.update(kwargs)
            return super(SandwichField, self).formfield(*args, **defaults)
    

    显然是因为 this line in django/contrib/admin/options.py 它指定了 models.IntegerField 应该是 widgets.AdminIntegerFieldWidget . 因为 models.PositiveIntegerField 继承自 模型.IntegerField ,因为 line 181 在字段的所有子类上循环,似乎没有办法防止在管理中重写小部件。

    这是一个真正的问题,因为我在我的站点和整个管理员中使用这个自定义字段及其自定义小部件,并且我不想为 override_fields 每次我想用这个领域。理想情况下,开发人员应该能够使用自定义字段,而不必每次都提供自定义管理。

    现在我继承了 forms.PositiveIntegerField 因为当从数据库中存储和检索时,它是一个正整数,我想利用已经存在的处理正整数的所有编码。

    目前看来 只有 解决方案是将我的字段更改为继承自 models.Field 然后复制并粘贴所有 PositiveIntegerField IntegerField 来自django代码的功能。还有别的办法吗?

    当然,我总是可以让我的formfield忽略发送给它的任何小部件,并且总是使用自定义小部件,但是当我主动 希望 重写小部件,这绝对可能发生。我只是不想让管理员覆盖我的小部件。

    1 回复  |  直到 6 年前
        1
  •  0
  •   ruddra    6 年前

    在模型管理中,需要将这些小部件添加到 formfield_overrides . 例如:

    class BaseModelAdmin(admin.ModelAdmin):
        formfield_overrides = {
            models.CharField: {'widget': forms.Textarea},
        }
    

    现在,您可以从这个类中对所有模型管理员进行子类划分,而不必为重写编写多余的代码。