如何用Django GeneratedField为Book模型获取首个AUTHOR类型Person?
问题解答
用Django的GeneratedField没法实现你要的这个需求,原因如下:
- GeneratedField的底层依赖数据库的生成列,它只能基于当前模型字段或直接关联的单条记录字段做简单计算,搞不定多对多关联里需要筛选、排序再取第一条的复杂逻辑。
- 要拿到书籍的第一个AUTHOR,得通过
PersonBook中间表关联PersonType筛选类型,再排序取第一个Person的ID——这种跨表的筛选+排序+取第一条的逻辑,不管是Django的GeneratedField封装能力,还是大部分数据库的生成列功能,都不支持。
给你两个实用的替代方案:
- 自定义模型属性
直接在Book模型里加个@property方法,实时查询获取第一个作者:
class Book(models.Model): title = models.TextField() people = models.ManyToManyField(Person, through="PersonBook") @property def author(self): # 筛选出当前书籍的AUTHOR类型关联,按id排序取第一个,存在则返回Person对象,否则返回None person_book = self.personbook_set.filter(person_type__name="AUTHOR").order_by("id").first() return person_book.person if person_book else None
- 自定义Manager预取
如果担心多次查询影响性能,可以用Manager提前通过子查询标注作者ID,再关联查询:
from django.db.models import Subquery, OuterRef class BookManager(models.Manager): def get_queryset(self): # 子查询获取当前书籍的第一个AUTHOR的ID author_subquery = PersonBook.objects.filter( book=OuterRef('pk'), person_type__name="AUTHOR" ).order_by('id').values('person__id')[:1] return super().get_queryset().annotate( _author_id=Subquery(author_subquery) ).select_related('_author') # 预取关联的Person对象 class Book(models.Model): title = models.TextField() people = models.ManyToManyField(Person, through="PersonBook") objects = BookManager() @property def author(self): return self._author if hasattr(self, '_author_id') else None
内容的提问来源于stack exchange,提问作者Rob Rose
相关产品推荐
相关产品推荐

