Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How do I exclude 'self' instance from a ManyToMany field which references the 'self' model?

I have a ‘Pizza’ model that can inherit ‘Toppings’ from another instance of ‘Pizza’.
When I go to update the Pizza, to add new toppings, I need to prevent the user from selecting the ‘self’ instance of Pizza in the parent list.

For Example: I create Margarita pizza with cheese and tomato toppings. I then create another Pizza (Pepperoni) and inherit all toppings form the Margarita. I need to stop Pepperoni from appearing in the ‘parents’ list to stop a circular reference.

models.py

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class Topping(models.Model):
    name = models.CharField(max_length=100)


class Pizza(models.Model):
    name = models.CharField(max_length=100)
    parents = models.ManyToManyField("self", symmetrical=False)
    toppings = models.ManyToManyField(Topping)

forms.py

class PizzaForm(ModelForm):

    toppings = forms.ModelMultipleChoiceField(
        queryset=Topping.objects.all(),
        widget=forms.CheckboxSelectMultiple,
        required=False
    )

    parents = forms.ModelMultipleChoiceField(
        queryset=Pizza.objects.all(),
        widget=forms.CheckboxSelectMultiple,
        required=False
    )

    class Meta:
        model = Pizza
        fields = '__all__'

views.py

class PizzaUpdateView(UpdateView):
    model = Pizza
    form_class = PizzaForm

I suspect I need to amend the parent queryset in PizzaForm to exclude a PK, but I’m unsure of how to hand this through to the form from my view.

>Solution :

You can override the init method of PizzaForm:

class PizzaForm(ModelForm):

    toppings = forms.ModelMultipleChoiceField(
        queryset=Topping.objects.all(),
        widget=forms.CheckboxSelectMultiple,
        required=False
    )

    parents = forms.ModelMultipleChoiceField(
        queryset=Pizza.objects.all(),
        widget=forms.CheckboxSelectMultiple,
        required=False
    )

    class Meta:
        model = Pizza
        fields = '__all__'

    def __init__(*args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['parents'].queryset = Pizza.objects.exclude(id=self.instance.id)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading