Dynamic fields in Django Admin

后端 未结 9 1462
失恋的感觉
失恋的感觉 2020-12-05 05:18

I want to have additional fields regarding value of one field. Therefor I build a custom admin form to add some new fields.

Related to the blogpost of jacobian 1 thi

相关标签:
9条回答
  • 2020-12-05 05:43

    You can create dynamic fields and fieldset using the form meta class. Sample code is given below. Add the loop logic as per you requirements.

    class CustomAdminFormMetaClass(ModelFormMetaclass):
        """
        Metaclass for custom admin form with dynamic field
        """
        def __new__(cls, name, bases, attrs):
            for field in get_dynamic_fields: #add logic to get the fields
                attrs[field] = forms.CharField(max_length=30) #add logic to the form field
            return super(CustomAdminFormMetaClass, cls).__new__(cls, name, bases, attrs)
    
    
    class CustomAdminForm(six.with_metaclass(CustomAdminFormMetaClass, forms.ModelForm)):
        """
        Custom admin form
        """
    
        class Meta:
            model = ModelName
            fields = "__all__" 
    
    
    class CustomAdmin(admin.ModelAdmin):
        """
        Custom admin 
        """
    
        fieldsets = None
        form = CustomAdminForm
    
        def get_fieldsets(self, request, obj=None):
            """
            Different fieldset for the admin form
            """
            self.fieldsets = self.dynamic_fieldset(). #add logic to add the dynamic fieldset with fields
            return super(CustomAdmin, self).get_fieldsets(request, obj)
    
        def dynamic_fieldset(self):
            """
            get the dynamic field sets
            """
            fieldsets = []
            for group in get_field_set_groups: #logic to get the field set group
                fields = []
                for field in get_group_fields: #logic to get the group fields
                    fields.append(field)
    
                fieldset_values = {"fields": tuple(fields), "classes": ['collapse']}
                fieldsets.append((group, fieldset_values))
    
            fieldsets = tuple(fieldsets)
    
            return fieldsets
    
    0 讨论(0)
  • 2020-12-05 05:44

    Maybe I am a bit late... However, I am using Django 3.0 and also wanted to dynamically ad some custom fields to the form, depending on the request.

    I end up with a solution similar to the one described by @tehfink combined with @little_birdie.

    However, just updating self.form.declared_fields as suggested didn't help. The result of this procedure is, that the list of custom fields defined in self.form.declared_fields always grows from request to request.

    I solved this by initialising this dictionary first:

    class ModelAdminGetCustomFieldsMixin(object):
        def get_fields(self, request, obj=None):
            fields = super().get_fields(request, obj=None)
            self.form.declared_fields = {}
            if obj:
                for custom_attribute in custom_attribute_list:
                    self.form.declared_fields.update({custom_attribute.name: custom_attribute.field})
            return fields
    

    where custom_attribute.field is a form field instance.

    Additionally, it was required to define a ModelForm, wherein during initialisation the custom fields have been added dynamically as well:

    class SomeModelForm(forms.ModelForm):
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            for custom_attribute in custom_attribute_list:
                self.fields[custom_attribute.name] = custom_attribute.field
    
    

    and use this ModelForm in the ModelAdmin.

    Afterwards, the newly defined attributes can be used in, e.g., a fieldset.

    0 讨论(0)
  • 2020-12-05 05:51

    not sure why that's not working, but could a possible workaround be to define the field statically (on the form) and then override it in the __init__?

    0 讨论(0)
提交回复
热议问题