Django/python querysets - adding another "child" queryset as an item to each list object? -
apologies if answer obvious - i'm new django/python & haven't been able find solution in searching far.
i have straightforward queryset, eg
members = librarymembers.objects.all()
with can do:-
for m in members: member_books = libraryborrows.objects.filter(member_id=m[u'id'])
what want though able serialize results json, looks this:-
{ "members": [ { "id" : "1", "name" : "joe bloggs" "books": [ { "name" : "five go exploring", "author" : "enid blyton", }, { "name" : "princess of mars", "author" : "edgar rice burroughs", }, ] } ] }
to mind, obvious thing try was:-
for m in members: m[u'books'] = libraryborrows.objects.filter(member_id=m[u'id'])
however i'm getting typeerror: 'libraryborrows' object not support item assignment
is there way achieve i'm after?
model instances not indeed not dicts. if want dicts instead of model instances, queryset.values()
friend - list of dicts required fields, , avoid overhead of retrieving unneeded fields database , building full-blown model instances.
>> members = librarymember.objects.values("id", "name") >> print members [{"id" : 1, "name" : "joe bloggs"},]
then code like:
members = librarymember.objects.values("id", "name") m in members: m["books"] = libraryborrows.objects.filter( member_id=m['id'] ).values("name", "author")
now still have issue 1 additionnal db query each parent row may not efficient, depending on number of librarymember. if have hundreds or more librarymember, better approach query on libraryborrow instead, including related fields librarymember, regroup rows based on librarymember id, ie:
from itertools import group_by def filter_row(row): 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') 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) row in group] } members.append(member)
nb : can seen premature optimization (and if have couple librarymember in db), trading hundreds or more queries 1 single query , bit of postprocessing makes real difference "real life" datasets.
Comments
Post a Comment