Django ModelChoiceField model formset creating form for every object

943 views Asked by At

I am trying to setup a model formset with a ModelChoiceField so that the user can create several forms and in each form they select one item from the queryset. However, when I render my formset, it is creating a form for each object in the queryset. Within each form, the ModelChoiceField is already set to the next object in the queryset. This is not desirable, I only want one form where the user should select the desired object and I will create them dynamically with JS. Basically I am nesting the applications formset inside of the rulerequest form.

Forms:

class ApplicationForm(BootstrapMixin, forms.ModelForm):

    name = forms.ModelChoiceField(
        queryset=Application.objects.all(),
        to_field_name='name',
        help_text='Application name',
        error_messages={
            'invalid_choice': 'Application not found.',
        }
    )

    class Meta:
        model = Application
        fields = [
            'name'
        ]
        help_texts = {
            'name': "Application name",
        }


class RuleRequestForm(BootstrapMixin, forms.ModelForm):

    class Meta:
        model = RuleRequest
        fields = [
            'name', 'description', 
        ]
        help_texts = {
            'name': 'Short name for the request',
            'description': "Buisness case and summary.",
        }

    def __init__(self, *args, **kwargs):

        super(RuleRequestForm, self).__init__(*args, **kwargs)

        data = kwargs.get('data')
        initial = kwargs.get('initial')

        application_formset = modelformset_factory(Application, form=ApplicationForm, extra=0, min_num=1)

        self.applications = application_formset(data=data, initial=initial, prefix='applications')

Models:

class Application(CreatedUpdatedModel):

    name = models.CharField(
        max_length=255,
        null=True
    )
    description = models.TextField(
        blank=True
    )

    def __str__(self):
        return self.name


class RuleRequest(CreatedUpdatedModel, ST2ExecuationModel):

    name = models.CharField(
        max_length=255
    )
    description = models.TextField(
        blank=False
    )
    applications = models.ManyToManyField(
        to=Application,
        related_name='rule_requests'
    )
1

There are 1 answers

0
alfonso.kim On

you can start with a simple approach:

in your view:

applications = Application.objects.all()
return render('template_name.html', request, applications)

in your template:

<select id="application-select">
{% for application in applications %}
   <option value="{{ application.name }}">{{ application.description }}</option>
{% endfor %}

<!-- in your javascript -->
$('#application-select').on('change', function (e) {
    var optionSelected = $("option:selected", this);
    var valueSelected = this.value;
    // do something with the selected option
});

Once you have defined behaviour for the forms, you can use Django's ModelForm to reduce the code.

please note that this is not a complete solution for your problem. It depends on how you want to create the forms.