所以我最近开始使用 Django,我遇到了书籍和作者之间多对多关系的情况 - 作为一个简单的例子 - 一本书可以有多个作者。
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField('Author', related_name='books')
def __str__(self):
return self.title
class Author(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
我的目标是获取 Book 的数据,但问题是当一本书有多个作者时,我为每个作者获得相同的书行,问题是 我可以有一个书行,其所有作者都存储在一个列表 ?而不是每个作者占一行。
以 JSON 形式获取数据的示例:
[
{
"id": 1,
"title": "Good Omens",
"authors__name": "Neil Gaiman"
},
{
"id": 1,
"title": "Good Omens",
"authors__name": "Terry Pratchett"
},
{
"id": 2,
"title": "The Lord of the Rings",
"authors__name": "J.R.R. Tolkien"
}
]
所以我想要这样的东西:
{
"id": 1,
"title": "Good Omens",
"authors__name": ["Neil Gaiman", "Terry Pratchett"]
},
虽然通过 python 代码实现这一点很容易,但我想要一个使用模型查询或 ORM 方法的解决方案,以获得一些性能和时间,因为数据会很大。
以下代码显示了一个负责获取数据并进行一些排序和过滤的方法,所有这些都使用查询:
def __model_query(self, model_class, fields=None, enum_fields=None, order_by=None, search=None, field_search=None):
queryset = model_class.objects.all()
# Apply ordering if specified
if order_by:
field_name, sort_order = order_by
if sort_order == "desc":
queryset = queryset.order_by(f"-{field_name}")
elif sort_order == "asc":
queryset = queryset.order_by(field_name)
# Apply general search if specified
if search:
search_filters = Q()
for field in fields:
search_filters |= Q(**{f"{field}__icontains": search})
queryset = queryset.filter(search_filters)
# Apply field-specific search if specified
if field_search:
search_filters = Q()
for field, value in field_search.items():
if enum_fields and field in enum_fields:
search_filters |= Q(**{f"{field}__exact": value})
else:
search_filters |= Q(**{f"{field}__icontains": value})
queryset = queryset.filter(search_filters)
return queryset
我目前使用的是sqlite3 db,所以我无法使用与Postgres db相关的任何方法。
我真的很感谢能够帮助我的人,我希望我提供了所需的所有详细信息。
我没有尝试太多解决方案,只是ChatGPT提供的解决方案,但都失败了。
您正在使用不支持
ArrayAgg
的db.sqlite3,因此您可以使用如下方式达到预期结果:
books = Book.objects.values('id', 'title', 'authors__name')
book_dict = {}
for book in books:
book_id = book['id']
if book_id not in book_dict:
book_dict[book_id] = {
'id': book_id,
'title': book['title'],
'authors__name': []
}
if book['authors__name']:
book_dict[book_id]['authors__name'].append(book['authors__name'])
books_list = list(book_dict.values())