Search code examples
djangodjango-formsformsetmodelchoicefield

how to create a Django form/formset with Modelchoice fields having values from different querysets


I would like to display simultaneously several modelchoicefields, each of them with data from the same model but having different querysets. To do so shall I use one formset or several forms to pass to the template?

I have tried with the formset.

Form:

class ValueForm(forms.Form):
    value = forms.ModelChoiceField(queryset = ValueTable.objects.all())

View:

filter_value1 = ValueTabel.objects.filter(group = 1)
filter_value2 = ValueTabel.objects.filter(group = 3)
TmpFormSet = formset_factory(ValueForm, extra=0)
form = TmpFormSet(queryset=filter_value1,filter_value2)

Here are my records in the database:

ValueTable(group, value):
1, Value1
1, Value2
1, Value3
2, Value4
3, Value5
3, Value6


Group(group, attribute)
1, attribute1
2, attribute2
3, attribute1

Selecting the attribute1 on the model Group (record 1 and 3), I would display simultaneously two forms with the following choices:

modelchoicefield 1:
Value1
Value2
Value3

modelchoicefield 2:
Value5
Value6

How can I add manually to the formset the two queryset?


Solution

  • A formset is used to display one form per model instance and only allows you to set custom parameters for all instances.

    What you are trying to achieve here is to dynamically set the queryset of the value field per instance (aka it's not the same for every instance), so I don't believe you will be able to achieve what you want with a formset.

    Just create a loop and instantiate each form manually by passing the proper queryset to each form field.

    With the example you gave it would look something like this:

    value_queryset1 = ValueTabel.objects.filter(group = 1)
    value_queryset2 = ValueTabel.objects.filter(group = 3)
    value_querysets = [value_queryset1, value_queryset2]
    value_forms = []
    
    for value_queryset in value_querysets:
        value_form = ValueForm()
        value_form.fields["value"].queryset = value_queryset
        value_forms.append(value_form)
    

    You could also override the init method of the ValueForm to make it look a bit less messy but technically they are the same.

    I hope it makes sense and helps you figure this out.