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

后端 未结 3 1645
余生分开走
余生分开走 2021-01-04 08:46

Given a model with ForeignKeyField (FKF) or ManyToManyField (MTMF) fields with a foreignkey to \'self\' how can I prevent self (recursive) selection within the Djan

相关标签:
3条回答
  • 2021-01-04 09:22

    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(
                id__exact=self.instance.id)
    
    0 讨论(0)
  • 2021-01-04 09:25

    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 =
                    form.base_fields[fieldname]._queryset.exclude(id=obj.id)
        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 :-)

    0 讨论(0)
  • 2021-01-04 09:30

    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.

    0 讨论(0)
提交回复
热议问题