Add a dynamic number of fields to Django admin form












0














I have 3 models "Configuration", "Process", and "ProcessConfiguration" as defined below:



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)


What I am trying to do is to add a new CharFeild to the Process admin form for each of the Configuration objects that have a particular entity flag set.



I thought I would be able to do this in a similar way to how I have added other fields to forms, but within a loop.



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)


When I print out the fields at the end of the init, I can see that the new fields have been added, however when I load the page I can only see the "test_above" field.



In my admin.py module I have registered the model to an admin class that I have created in another module:



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

admin.site.register(Process, ProcessAdmin)


Here is the ProcessAdmin snippet model_admin module:



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)


The end goal of this is when an admin user is adding a new process, then they should be able to add new 'ProcessConfiguration' that are associated with the model that they are creating.



Is this the right way to approach this issue?










share|improve this question





























    0














    I have 3 models "Configuration", "Process", and "ProcessConfiguration" as defined below:



    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)


    What I am trying to do is to add a new CharFeild to the Process admin form for each of the Configuration objects that have a particular entity flag set.



    I thought I would be able to do this in a similar way to how I have added other fields to forms, but within a loop.



    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)


    When I print out the fields at the end of the init, I can see that the new fields have been added, however when I load the page I can only see the "test_above" field.



    In my admin.py module I have registered the model to an admin class that I have created in another module:



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

    admin.site.register(Process, ProcessAdmin)


    Here is the ProcessAdmin snippet model_admin module:



    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)


    The end goal of this is when an admin user is adding a new process, then they should be able to add new 'ProcessConfiguration' that are associated with the model that they are creating.



    Is this the right way to approach this issue?










    share|improve this question



























      0












      0








      0


      1





      I have 3 models "Configuration", "Process", and "ProcessConfiguration" as defined below:



      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)


      What I am trying to do is to add a new CharFeild to the Process admin form for each of the Configuration objects that have a particular entity flag set.



      I thought I would be able to do this in a similar way to how I have added other fields to forms, but within a loop.



      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)


      When I print out the fields at the end of the init, I can see that the new fields have been added, however when I load the page I can only see the "test_above" field.



      In my admin.py module I have registered the model to an admin class that I have created in another module:



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

      admin.site.register(Process, ProcessAdmin)


      Here is the ProcessAdmin snippet model_admin module:



      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)


      The end goal of this is when an admin user is adding a new process, then they should be able to add new 'ProcessConfiguration' that are associated with the model that they are creating.



      Is this the right way to approach this issue?










      share|improve this question















      I have 3 models "Configuration", "Process", and "ProcessConfiguration" as defined below:



      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)


      What I am trying to do is to add a new CharFeild to the Process admin form for each of the Configuration objects that have a particular entity flag set.



      I thought I would be able to do this in a similar way to how I have added other fields to forms, but within a loop.



      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)


      When I print out the fields at the end of the init, I can see that the new fields have been added, however when I load the page I can only see the "test_above" field.



      In my admin.py module I have registered the model to an admin class that I have created in another module:



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

      admin.site.register(Process, ProcessAdmin)


      Here is the ProcessAdmin snippet model_admin module:



      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)


      The end goal of this is when an admin user is adding a new process, then they should be able to add new 'ProcessConfiguration' that are associated with the model that they are creating.



      Is this the right way to approach this issue?







      python django python-3.x django-models django-forms






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 21 at 20:04

























      asked Nov 21 at 2:05









      NeuroWinter

      5010




      5010
























          1 Answer
          1






          active

          oldest

          votes


















          1














          I managed to sort this out by using the admin.StackedInline class:



          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')


          And then adding this as to the process admin class using this:



          inlines = [ProcessConfigurationInline]





          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53404343%2fadd-a-dynamic-number-of-fields-to-django-admin-form%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            I managed to sort this out by using the admin.StackedInline class:



            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')


            And then adding this as to the process admin class using this:



            inlines = [ProcessConfigurationInline]





            share|improve this answer


























              1














              I managed to sort this out by using the admin.StackedInline class:



              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')


              And then adding this as to the process admin class using this:



              inlines = [ProcessConfigurationInline]





              share|improve this answer
























                1












                1








                1






                I managed to sort this out by using the admin.StackedInline class:



                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')


                And then adding this as to the process admin class using this:



                inlines = [ProcessConfigurationInline]





                share|improve this answer












                I managed to sort this out by using the admin.StackedInline class:



                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')


                And then adding this as to the process admin class using this:



                inlines = [ProcessConfigurationInline]






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Dec 3 at 19:26









                NeuroWinter

                5010




                5010






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53404343%2fadd-a-dynamic-number-of-fields-to-django-admin-form%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    404 Error Contact Form 7 ajax form submitting

                    How to know if a Active Directory user can login interactively

                    TypeError: fit_transform() missing 1 required positional argument: 'X'