Добавить динамическое количество полей в форму администратора Django - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть 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)

Я пытаюсь добавить новый 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 я зарегистрировал модель в классе администратора, который я создал в другом модуле:

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 голосов
/ 03 декабря 2018

Мне удалось разобраться, используя класс 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]
...