向Django管理表单添加动态数量的字段

时间:2018-11-21 02:05:19

标签: python django python-3.x django-models django-forms

我有3种模型,分别定义为“配置”,“过程”和“ ProcessConfiguration”:

class Configuration(models.Model):

    name                = models.CharField(max_length=MAX_CONFIGURATION_NAME_LEN,
                                       unique=True, db_index=True)
    description         = models.TextField(blank=True)
    validation          = models.CharField(max_length=MAX_CONFIGURATION_VALIDATION_LEN,
                                       blank=True)
    entity              = models.CharField(max_length=MAX_CONFIGURATION_ENTITY_LEN,
                                       blank=False)
    is_customer_visible = models.BooleanField(default=False, editable=True)



class ProcessConfiguration(models.Model):

    process       = models.ForeignKey(Process, on_delete=models.CASCADE, db_index=True)
    configuration = models.ForeignKey(Configuration, on_delete=models.CASCADE, db_index=True)
    value         = models.TextField()
    created       = models.DateTimeField(editable=False, auto_now_add=True, db_index=True)

    def __str__(self):
        return self.process.name + ": " + self.configuration.name + " = " + self.value[:80]

    class Meta:
        unique_together = ('process', 'configuration')

class Process(models.Model):
    name          = models.CharField(max_length=MAX_PROCESS_NAME_LEN)

我想做的是为每个设置了特定实体标志的Configuration对象的Process admin窗体添加一个新的CharFeild。

我认为我可以像在窗体中添加其他字段一样的方式执行此操作,但是要在一个循环中进行。

class ProcessCreateForm(forms.ModelForm):

    test_above = forms.CharField()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        extented_configurations = 
        Configuration.objects.filter(entity='proc',
                                     is_customer_visible=True)

        for config_item in extented_configurations:
            kwargs      = {
                           'label': "123",
                           'required': False
                          }
            field_class = forms.CharField
            self.fields[config_item.name] = field_class(**kwargs)

当我在初始化末尾打印出字段时,我可以看到已经添加了新字段,但是,当我加载页面时,我只能看到“ test_above”字段。

在admin.py模块中,我已将模型注册到在另一个模块中创建的admin类中:

from X.models       import Process
from X.model_admins import ProcessAdmin

admin.site.register(Process, ProcessAdmin)

这是ProcessAdmin片段model_admin模块:

class ProcessAdmin(admin.ModelAdmin):
    list_display = ['name']

    def get_form(self, request, obj=None, **kwargs):
        from X.admin_forms import ProcessCreateForm
        defaults = {}
        defaults['form'] = ProcessCreateForm
        defaults.update(kwargs)
        return super().get_form(request, obj, **defaults)

此操作的最终目标是当管理员用户添加新流程时,他们应该能够添加与他们所创建的模型相关联的新“ ProcessConfiguration”。

这是解决此问题的正确方法吗?

1 个答案:

答案 0 :(得分:1)

我设法通过使用admin.StackedInline类来解决此问题:

class ProcessConfigurationInline(admin.StackedInline):                                                   
    """                                                                                        
    Inline form for process configurations.                                                    
    """                                                                                        

    model          = ProcessConfiguration                                                      
    config_formset = modelformset_factory(Configuration, fields=('__all__'))                   
    extra          = 1                                                                         

    def formfield_for_foreignkey(self, db_field, request=None, **kwargs):                      
        """                                                                                    
        Limit the types of configuration items you can add.                                    
        """                                                                                    
        field = super(ProcessConfigurationInline, self). \                                     
                       formfield_for_foreignkey(db_field, request, **kwargs)                   
        if db_field.name == 'configuration':                                                   
            field.queryset = field.queryset.filter(entity='process')                           

然后使用以下代码将其添加到流程管理类中:

inlines = [ProcessConfigurationInline]