如何在Django ORM中实现作者关联书籍名称的聚合查询?
实现方案
首先确认你的Django模型结构(若未定义可参考):
from django.db import models class Author(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=100, verbose_name='作者姓名') class Meta: verbose_name = '作者' verbose_name_plural = verbose_name class Book(models.Model): id = models.AutoField(primary_key=True) author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books', verbose_name='作者') book_name = models.CharField(max_length=200, verbose_name='书籍名称') class Meta: verbose_name = '书籍' verbose_name_plural = verbose_name
方法一:模型属性实现(通用兼容)
在Author模型中添加属性方法,直接拼接并格式化书籍名称:
@property def formatted_books(self): # 获取当前作者的所有书籍名称,用逗号分隔 book_list = self.books.values_list('book_name', flat=True) joined_books = ', '.join(book_list) # 用strong标签包裹拼接结果 return f'<strong>{joined_books}</strong>'
查询时用prefetch_related优化关联查询性能:
# 预加载关联书籍,避免N+1查询问题 authors = Author.objects.prefetch_related('books').all() # 遍历输出目标格式数据 for author in authors: print({ 'id': author.id, '作者姓名': author.name, '书籍名称': author.formatted_books })
如果在Django模板中展示,需添加safe过滤器让HTML标签生效:
{{ author.formatted_books|safe }}
方法二:数据库聚合查询(适配PostgreSQL)
若使用PostgreSQL数据库,可直接用StringAgg聚合函数在数据库层面完成拼接,性能更优:
from django.contrib.postgres.aggregates import StringAgg authors = Author.objects.annotate( # 聚合拼接书籍名称 book_names=StringAgg('books__book_name', delimiter=', ') ).annotate( # 拼接strong标签生成最终格式 formatted_books=models.Concat( models.Value('<strong>'), 'book_names', models.Value('</strong>'), output_field=models.TextField() ) ).values('id', 'name', 'formatted_books') # 转换为列表格式输出 result = list(authors) print(result)
最终输出结果将完全匹配你需要的格式:
| id | 作者姓名 | 书籍名称 |
|---|---|---|
| 1 | Tom | rescue a person, be a doctor |
内容的提问来源于stack exchange,提问作者user571102
相关产品推荐
相关产品推荐

