Django/python 查询集 - 将另一个"child"查询集作为项目添加到每个列表对象?



抱歉,如果答案很明显 - 我对 django/python 很陌生,到目前为止在我的搜索中还没有找到解决方案。

我有一个简单的查询集,例如

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'])

但是我收到类型错误:"图书馆借用"对象不支持项目分配

有什么方法可以实现我所追求的吗?

模型实例实际上并不是字典。现在,如果您想要字典而不是模型实例,那么Queryset.values()是您的朋友 - 您将获得仅包含必填字段的字典列表,并且避免了从数据库中检索不需要的字段和构建成熟的模型实例的开销。

>> 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")

现在,您仍然必须为每个父行发出一个额外的数据库查询,这可能效率不高,具体取决于 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 就会如此),但为单个查询和一些后处理交换数百个或更多查询通常会对"现实生活"数据集产生真正的影响。

好吧,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)

我还发现了直到今天我才听说过的 DjangoFullSerializers:

http://code.google.com/p/wadofstuff/wiki/DjangoFullSerializers

最新更新