【问题标题】:How do I dynamically exclude a non-model field from the admin?如何从管理员中动态排除非模型字段?
【发布时间】:2023-03-25 10:45:01
【问题描述】:

我已将自定义字段添加到 ModelForm 以供管理员使用:

class MyModel(models.Model):
    name = models.CharField(max_length=64)
     ...etc...

class MyModelAdminForm(forms.ModelForm):
    dynamicfield = forms.IntegerField()

    def __init__(self, *args, **kwargs):
        super(MyModelAdminForm, self).__init__(*args, **kwargs)
        if 'instance' in kwargs:
            #remove dynamicfield from the form, somehow?

    def save(self, *args, **kwargs):
        #do something with dynamicfield
        super(MyModelAdminForm, self).save(*args, **kwargs)

    class Meta:
        model = MyModel

class MyModelAdmin(admin.ModelAdmin):
    form = MyModelAdminForm

admin.site.register(MyModel, MyModelAdmin)

此字段的目的是收集初始对象创建期间所需的其他数据。因此,它只应在创建新对象时出现(检查“实例”)。

我遇到的问题是在编辑现有对象时使该字段消失。我试过了:

self.fields['dynamicfield'].widget = self.fields['dynamicfield'].hidden_widget()

但这只会去掉文本输入字段,而不是标签。

我也尝试过这些变体(在super() 调用之前,也使用 base_fields 代替字段):

del self.fields['dynamicfield'] #yields error:

TemplateSyntaxError at /admin/db/myapp/mymodel/6/
Caught an exception while rendering: Key 'dynamicfield' not found in Form


self.fields['dynamicfield'].hidden = True #Does nothing.

self.fields['dynamicfield'] = None #yields error:

TemplateSyntaxError at /admin/db/catalog/product/6/
Caught an exception while rendering: 'NoneType' object has no attribute 'label'    

这些调用 super() 之前也尝试过,但也失败了:

del self.base_fields['dynamicfield'] #yields error:
TemplateSyntaxError at /admin/db/myapp/mymodel/6/
Caught an exception while rendering: Key 'dynamicfield' not found in Form

【问题讨论】:

    标签: django django-admin django-forms


    【解决方案1】:

    试试这个:

        def __init__(self, *args, **kwargs):
    
            if 'instance' in kwargs:
                del self.base_fields['dynamicfield']
            super(MyModelAdminForm, self).__init__(*args, **kwargs)
    

    【讨论】:

    • 也已经试过了。与 del self.fields['dynamicfield'] 完全相同的错误(上图)。
    【解决方案2】:

    如果删除不起作用(我不知道为什么),那么动态添加呢?

    def __init__(self, *args, **kwargs):
        super(MyModelAdminForm, self).__init__(*args, **kwargs)
        if 'instance' not in kwargs:
           self.fields['dynamicfield'] = forms.IntegerField()
    

    这里还有一个关于如何create dynamic forms 的链接。 (我认为甚至是创建 Django 的那个人?)

    【讨论】: