[Fixed]-How to prevent self (recursive) selection for FK / MTM fields in the Django Admin


You can use a custom ModelForm in the admin (by setting the “form” attribute of your ModelAdmin subclass). So you do it the same way in the admin as you would anywhere else.


Carl is correct, here’s a cut and paste code sample that would go in admin.py

I find navigating the Django relationships can be tricky if you don’t have a solid grasp, and a living example can be worth 1000 time more than a “go read this” (not that you don’t need to understand what is happening).

class MyForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['myManyToManyField'].queryset = MyModel.objects.exclude(


You can also override the get_form method of the ModelAdmin like so:

def get_form(self, request, obj=None, **kwargs):
    Modify the fields in the form that are self-referential by
    removing self instance from queryset
    form = super().get_form(request, obj=None, **kwargs)
    # obj won't exist yet for create page
    if obj:
        # Finds fieldnames of related fields whose model is self
        rmself_fields = [f.name for f in self.model._meta.get_fields() if (
            f.concrete and f.is_relation and f.related_model is self.model)]
        for fieldname in rmself_fields:
            form.base_fields[fieldname]._queryset =
    return form

Note that this is a on-size-fits-all solution that automatically finds self-referencing model fields and removes self from all of them 🙂


I like the solution of checking at save() time:

    def save(self, *args, **kwargs):
        # call full_clean() that in turn will call clean()
        return super().save(*args, **kwargs)

    def clean(self):
        obj = self
        parents = set()
        while obj is not None:
            if obj in parents:
                raise ValidationError('Loop error', code='infinite_loop')
            obj = obj.parent

Leave a comment