如何在与手动定义的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)