How do I create and save dynamic fields in Django ModelAdmin?(如何在 Django ModelAdmin 中创建和保存动态字段?)
问题描述
我有一些模型:
class GroupType(models.Model):
    name = models.CharField(max_length=255)
class Group(models.Model):
    name = models.CharField(max_length=255)
    group_type = models.ForeignKey(GroupType)
class Person(models.Model):
    name = models.CharField(max_length=255)
    groups = models.ManyToManyField(Group, related_name="+")
但在 ModelAdmin 中,我想为每个组类型动态添加字段.因此,如果我有两个组类型 public、private,我希望管理表单显示两个字段 public_groups 和 private_groups 而不是实际的 db 字段 groups.
But in the ModelAdmin I'd like to dynamically add fields for each group type. So if I have two group types public, private, I'd like the admin form to show two fields public_groups and private_groups instead of the actual db field groups.
更多信息
我尝试创建自定义表单来动态添加字段:
I've tried creating a custom form to add the fields dynamically:
class PersonAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PersonAdminForm, self).__init__(*args, **kwargs)
        new_fields = {}
        for group_type in GroupType.objects.all():
            field_name = "{0}_groups".format(group_type.name.lower())
            qs = Group.objects.filter(group_type=group_type)
            field_field = forms.ModelMultipleChoiceField(queryset=qs)
            new_fields[field_name] = field_field
        self.fields.update(new_fields)
    class Meta:
        model = Person
        fields = '__all__'
就将字段添加到表单而言,这似乎起到了作用.但是保存这些字段并将它们添加到 PersonAdmin 不起作用.如果我将字段显式添加到 PersonAdmin 上的 fields 属性,我会得到:
Which seems to do the trick as far as adding the fields to the form. But saving those fields and and adding them to the PersonAdmin doesn't work. If I add the fields explicitly to the fields attribute on the PersonAdmin I get:
FieldError: Unknown field(s) (public_groups, private_groups) specified for Person. Check fields/fieldsets/exclude attributes of class PersonAdmin.
在尝试通过自定义 get_formsets 方法动态"添加它们时,我也得到了同样的结果:
I also get the same thing when trying to add them "dynamically" through a custom get_formsets method:
def get_fieldsets(self, request, obj=None):
    fieldsets = super(PersonAdmin, self).get_fieldsets(request, obj)
    print(self.form.fields)
    fieldsets[0][1]['fields'].extend(['public_groups', 'private_groups'])
    return fieldsets
推荐答案
以下代码完美运行.ModelForm 上重写的 __init__ 和 clean 方法添加了动态字段并定义了值的保存方式.
The following code worked perfectly. The overridden __init__ and clean methods on the ModelForm adds the dynamic fields and defines how the values should be saved.
重写的 get_form 和 get_fieldsets 以及 AdminModel 上的 fieldsets 属性确保动态表单字段显示在管理员中.
The overridden get_form and get_fieldsets together with the fieldsets attribute on the AdminModel make sure the dynamic form fields get displayed in the admin.
class PersonAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PersonAdminForm, self).__init__(*args, **kwargs)
        new_fields = {}
        initial = self.instance.groups.all()
        for group_type in GroupType.objects.all():
            field_name = '{0}_groups'.format(group_type.name.lower())
            qs = Group.objects.filter(group_type=group_type)
            field = forms.ModelMultipleChoiceField(
                queryset=qs,
                required=False,
                initial=initial,
            )
            new_fields[field_name] = field
        self.fields.update(new_fields)
    def clean(self):
        cleaned_data = super(PersonAdminForm, self).clean()
        groups = []
        for group_type in GroupType.objects.all():
            gt_name = '{0}_groups'.format(group_type.name.lower())
            groups.extend(cleaned_data.get(gt_name))
        self.instance.groups.clear()
        self.instance.groups.add(*groups)
        return cleaned_data
    class Meta:
        model = Person
        fields = '__all__'
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    form = PersonAdminForm
    # using the fieldsets attribute instead of fields in order to dynamically
    # add group type fields later.
    fieldsets = (
        (None, {
            'fields': (
                'name',
            ),
        }),
    )
    def get_form(self, request, obj=None, **kwargs):
        kwargs['fields'] = flatten_fieldsets(self.declared_fieldsets)
        return super(PersonAdmin, self).get_form(request, obj, **kwargs)
    def get_fieldsets(self, request, obj=None):
        fieldsets = super(PersonAdmin, self).get_fieldsets(request, obj)
        newfieldsets = list(fieldsets)
        fields = []
        for group_type in GroupType.objects.all():
            fields.append('{0}_groups'.format(group_type.name.lower()))
        newfieldsets.append(['Groups', {'fields': fields}])
        return newfieldsets
                        这篇关于如何在 Django ModelAdmin 中创建和保存动态字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何在 Django ModelAdmin 中创建和保存动态字段?
				
        
 
            
        - 如何在 python3 中将 OrderedDict 转换为常规字典 2022-01-01
 - python check_output 失败,退出状态为 1,但 Popen 适用于相同的命令 2022-01-01
 - 如何将一个类的函数分成多个文件? 2022-01-01
 - 分析异常:路径不存在:dbfs:/databricks/python/lib/python3.7/site-packages/sampleFolder/data; 2022-01-01
 - 如何在 Python 的元组列表中对每个元组中的第一个值求和? 2022-01-01
 - 沿轴计算直方图 2022-01-01
 - pytorch 中的自适应池是如何工作的? 2022-07-12
 - padding='same' 转换为 PyTorch padding=# 2022-01-01
 - python-m http.server 443--使用SSL? 2022-01-01
 - 使用Heroku上托管的Selenium登录Instagram时,找不到元素';用户名'; 2022-01-01
 
				
				
				
				