Django Admin - 使用通过模型过滤 ManyToManyField



如何在与手动定义的through模型具有ManyToManyField关系的对象的管理页面中筛选查询集?

给定 models.py

class Foo(models.Model):
    foo_field1 = models.CharField(max_length=50)
class Main(models.Model):
    main_field1 = models.CharField(max_length=50)
    m2mfield = models.ManyToManyField(Foo, through="FooBar")
class FooBar(models.Model):
    main = models.ForeignKey(Main, on_delete=models.CASCADE)
    foo = models.ForeignKey(Foo, on_delete=models.CASCADE)
    new_field = models.CharField(max_length=50)

内 admin.py

class M2MInlineAdmin(admin.TabularInline):
    model = Main.m2mfield.through
    extra = 1
class MainAdmin(admin.ModelAdmin):
   inlines = [M2MInlineAdmin,]
   ...
    def formfield_for_manytomany(self, db_field, request, **kwargs):
        print('called formfield_for_manytomany')
        return super().formfield_for_manytomany(db_field, request, **kwargs)
    def get_field_queryset(self, db, db_field, request):
        print('called get_field_queryset')
        return super().get_field_queryset(db, db_field, request)

我尝试访问这两种方法,但是如果我指定through表,则不会调用它们。但是,如果 ManyToMany 关系简单地定义为这样,它们确实会被调用:

class Main(models.Model):
    main_field1 = models.CharField(max_length=50)
    m2mfield = models.ManyToManyField(Foo)

有没有一种方法可以在指定直通表时过滤查询集(同时能够访问request上下文(?

编辑:

当 ManyToManyField 指定了through模型时,确实会调用这些方法,前提是 modelAdmin 类中没有指定fieldsets

定义fieldsets时如何访问这些方法?

formfield_for_manytomany方法似乎仅在使用默认形式时才调用。当定义字段集时,它使用不同的形式,这就是为什么没有调用上述方法的原因。

由于您对多对多字段使用表格管理,因此您可以覆盖get_queryset以使用字段进行筛选。

class M2MInlineAdmin(admin.TabularInline):
    model = Main.fruits.through
    extra = 1
    def get_queryset(self, request):
        qs = super(M2MInlineAdmin, self).get_queryset(request)
        qs = qs.filter(some_arg=some_value)
        return qs

或者,您可以编写自定义模型表单并在 admin 而不是默认表单中使用它。

class MainAdminForm(forms.ModelForm):
    class Meta:
        model = Main
        fields = '__all__'
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # custom setup

class MainAdmin(admin.ModelAdmin):
    form = MainAdminForm

可以在内联类上使用 formfield_for_foreignkey() 方法。

class M2MInlineAdmin(admin.TabularInline):
    model = Main.m2mfield.through
    extra = 1
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "car":
            kwargs["queryset"] = Car.objects.filter(owner=request.user)
        return super().formfield_for_foreignkey(db_field, request, **kwargs)

相关内容

  • 没有找到相关文章

最新更新