如何通过仅存在于子类的多态属性筛选Django Book模型?
Django-polymorphic关联模型筛选问题解决办法
问题背景
用Django-polymorphic搭建了包含Book、Author(多态父模型)、AnonymousAuthor(子类)的模型结构后,想筛选出由别名为"foobar"的匿名作者创作的图书,直接用Book.objects.filter(author__known_as="foobar")会报错,提示无法识别known_as字段;仅筛选匿名作者的图书可以通过ContentType实现,但没法进一步按别名筛选。
可行解决方案
1. 通过子类反向关联直接筛选
利用Django-polymorphic自动生成的子类反向关联(子类名称小写),直接指定子类字段筛选:
Book.objects.filter(author__anonymousauthor__known_as="foobar")
也可以从AnonymousAuthor出发,反向关联到Book:
# 获取符合条件的图书集合 target_books = Book.objects.filter( id__in=AnonymousAuthor.objects.filter(known_as="foobar").values_list('book', flat=True) )
2. 结合ContentType与子类字段精准筛选
先限定作者类型为AnonymousAuthor,再通过子类字段筛选,避免跨类型查询:
from django.contrib.contenttypes.models import ContentType aa_ctype = ContentType.objects.get_for_model(AnonymousAuthor) target_books = Book.objects.filter( author__polymorphic_ctype=aa_ctype, author__anonymousauthor__known_as="foobar" )
3. 适配django-filters的实现
如果要在django-filters中使用该筛选规则,可定义如下过滤器类:
import django_filters from .models import Book class BookFilter(django_filters.FilterSet): # 自定义筛选字段,对应匿名作者的别名 author_known_as = django_filters.CharFilter( field_name='author__anonymousauthor__known_as', lookup_expr='exact' ) class Meta: model = Book fields = ['author_known_as']
原理说明
Django-polymorphic会为每个多态子类创建一个反向关联到父模型的关系(默认名称为子类名小写),通过父模型__子类模型__子类字段的链式调用,ORM就能正确定位到子类特有的字段,从而实现跨多态模型的筛选。
内容的提问来源于stack exchange,提问作者Martin Thoma
相关产品推荐
相关产品推荐

