Filter dropdown options in Django inline formset based on attribute of through model

Hello again Carlton (apologies for spelling your name wrong previously :slight_smile: )

I figured it out!

I had to create a new form and override the __init__ method like you said. The newly created form inherits the ModelForm class. I knew I was going to be using the “ingredient” field from my model when constructing the inline formset, so I filtered that field in the __init__ method by the current user’s Ingredient objects.

Sidebar: It turns out that adding a specific ModelChoiceField wasn’t necessary, but I added it anyway to fill in the empty_label placeholder text for styling purposes.

I then had to pass the newly created form into the inlineformset_factory construction function with form=.

Finally, when creating the formset in my views, I had to pass in a new form_kwargs={'user': request.user} argument.

No changes were required to my models.

Here are is my updated forms.py (I moved the inlineformset_factory function out of views and into forms):

class ItemIngredientForm(forms.ModelForm):
    def __init__(self, *args, user, **kwargs):
        self.user = user
        super().__init__(*args, **kwargs)
        self.fields['ingredient'].queryset = Ingredient.objects.filter(user=self.user)

    ingredient = forms.ModelChoiceField(queryset=Ingredient.objects.all(), empty_label="Select an ingredient...") # added this for styling purposes only, the queryset arguement here doesn't appear to do anything given the presence of the queryset in the __init__ function, although including the queryset here seems to be required to get the code to work

IngredientQuantityFormset = inlineformset_factory(
    MenuItem, IngredientQuantity, form=ItemIngredientForm, fields=('ingredient', 'ingredientQuantity'), can_delete=True, extra=0
)

And here is my updated views.py:

def ItemUpdate(request, pk):
    item = MenuItem.objects.get(id=pk)
    user = request.user

    form = ItemCreateForm(instance=item)
    formset = IngredientQuantityFormset(instance=item, form_kwargs={'user': request.user})

    if request.method == 'POST':
        form = ItemCreateForm(request.POST, instance=item)
        formset = IngredientQuantityFormset(request.POST, instance=item, form_kwargs={'user': request.user})

# rest of view...

Thanks so much for pointing me in the right direction here! I was stuck on this for weeks! Feels good to get moving again!

1 Like