Django/python查询集-添加另一个;“儿童”;是否将queryset设置为每个列表对象的一项?
如果这个问题的答案显而易见,我深表歉意-我对django/python非常陌生&到目前为止,我还没有在搜索中找到解决方案 我有一个直截了当的问题Django/python查询集-添加另一个;“儿童”;是否将queryset设置为每个列表对象的一项?,python,django,typeerror,django-queryset,Python,Django,Typeerror,Django Queryset,如果这个问题的答案显而易见,我深表歉意-我对django/python非常陌生&到目前为止,我还没有在搜索中找到解决方案 我有一个直截了当的问题 members = LibraryMembers.objects.all() 有了这个,我可以做到:- for m in members: member_books = LibraryBorrows.objects.filter(member_id=m[u'id']) 但我真正想要的是能够将结果序列化为json,所以看起来像这样:- { "
members = LibraryMembers.objects.all()
有了这个,我可以做到:-
for m in members:
member_books = LibraryBorrows.objects.filter(member_id=m[u'id'])
但我真正想要的是能够将结果序列化为json,所以看起来像这样:-
{
"members":
[
{
"id" : "1",
"name" : "Joe Bloggs"
"books":
[
{
"name" : "Five Go Exploring",
"author" : "Enid Blyton",
},
{
"name" : "Princess of Mars",
"author" : "Edgar Rice Burroughs",
},
]
}
]
}
在我看来,最明显的尝试是:-
for m in members:
m[u'books'] = LibraryBorrows.objects.filter(member_id=m[u'id'])
但是我得到了TypeError:“LibraryBorrows”对象不支持项分配
有什么方法可以实现我想要的吗?嗯
m
是LibraryMember
对象,所以你不能把它当作字典。作为旁注:大多数人不以复数形式命名模型,因为它们只是一个建模对象的类,而不是对象的集合
一种可能的解决方案是列出一个字典列表,其中包含两个对象所需的值,类似于一行:
o = [ { "id": m.id, "name": m.name, "books": [{"name": b.name, "author": b.author} for b in m.libraryborrows_set.all()] } for m in LibraryMembers.objects.all()]
请注意,您可以使用获取给定成员的书籍。为了更加清晰:
o = []
for m in LibraryMembers.objects.all():
member_books = [{"name": b.name, "author": b.author} for b in m.libraryborrows_set.all()]
o.append( { "id": m.id, "name": m.name, "books": member_books } )
编辑:
要序列化所有字段,请执行以下操作:
members = []
for member in LibraryMembers.objects.all():
member_details = {}
for field in member._meta.get_all_field_names():
member_details[field] = getattr(member, field)
books = []
for book in member.librayborrows_set.all():
book_details = {}
for field in book._meta.get_all_field_names():
book_details[field] = getattr(book, field)
books.append(book_details)
member_details['books'] = books
members.append(member_details)
我还发现了我今天才听说的DjangoullSerializer:
模型实例实际上不是dict。现在,如果您想要dict而不是模型实例,那么
Queryset.values()
是您的朋友-您可以得到一个dict列表,其中只包含必需的字段,并且可以避免从数据库检索不需要的字段和构建完整的模型实例的开销
>> members = LibraryMember.objects.values("id", "name")
>> print members
[{"id" : 1, "name" : "Joe Bloggs"},]
然后,您的代码将如下所示:
members = LibraryMember.objects.values("id", "name")
for m in members:
m["books"] = LibraryBorrows.objects.filter(
member_id=m['id']
).values("name", "author")
现在,您仍然必须为每个父行发出一个额外的db查询,根据LibraryMember的数量,这可能没有那么有效。如果您有数百个或更多LibraryMember,更好的方法是查询LibraryBorrow,包括LibraryMember中的相关字段,然后根据LibraryMember id重新分组行,即:
from itertools import group_by
def filter_row(row):
for name in ("librarymember__id", "librarymember__name"):
del row[name]
return row
members = []
rows = LibraryBorrow.objects.values(
'name', 'author', 'librarymember__id', 'librarymember__name'
).order_by('librarymember__id')
for key, group in group_by(rows, lambda r: r['librarymember__id']):
group = list(group)
member = {
'id' : group[0]['librarymember_id'],
'name':group[0]['librarymember_name']
'books' = [filter_row(row) for row in group]
}
members.append(member)
注意:这可能被视为过早的优化(如果数据库中只有几个LibraryMember),但用数百个或更多查询交换一个查询和一点后处理通常会对“真实”数据集产生真正的影响。您应该使用。开始接收项目。.filter再次为您提供查询集。one_entry=entry.objects.get(pk=1)如果您展示了您的模型代码,尤其是两个模型之间的关系,这会很有帮助。没有内置关系(因为数据是如何从外部源填充的)。它只是两个单独的类,包含一组字段,基于字段值的多对一关系,如我的示例所示。给他们全部命名是。。。痛苦:\n我会尝试一下你的建议&看看它是否能让我有所收获,谢谢。当你可以使用
Queryset.values()时,为什么要构建完整的模型实例,然后使用\uuuu getattribute\uuuuuuu
(FWIW它应该是getattr(实例,名称)
)
返回完全相同的dict而不需要所有模型实例的开销?谢谢各位,这看起来很有希望。非常感谢@布鲁诺德修利尔斯:更正,谢谢。。。我有调用魔术方法的坏习惯,比如\uuu getattribute\uuu()
。