python - Django: optimizing many to many query -
i have post , tag models:
class tag(models.model): """ tag blog entry """ title = models.charfield(max_length=255, unique=true) class post(models.model): """ blog entry """ tags = models.manytomanyfield(tag) title = models.charfield(max_length=255) text = models.textfield() i need output list of blog entries , set of tags each post. able 2 queries, using workflow:
- get list of posts
- get list of tags used in posts
- link tags posts in python
i having trouble last step, here code came with, in gives me 'tag' object has no attribute 'post__id'
#getting posts posts = post.objects.filter(published=true).order_by('-added')[:20] #making disc, {5:<post>} post_list = dict([(obj.id, obj) obj in posts]) #gathering ids list id_list = [obj.id obj in posts] #tags used in given posts objects = tag.objects.select_related('post').filter(post__id__in=id_list) relation_dict = {} obj in objects: #here get: 'tag' object has no attribute 'post__id' relation_dict.setdefault(obj.post__id, []).append(obj) id, related_items in relation_dict.items(): post_list[id].tags = related_items can see error there? how can solve task using django orm, or have write custom sql?
edit:
i able solve raw query:
objects = tag.objects.raw(""" select bpt.post_id, t.* blogs_post_tags bpt, blogs_tag t bpt.post_id in (""" + ','.join(id_list) + """) , t.id = bpt.tag_id """) relation_dict = {} obj in objects: relation_dict.setdefault(obj.post_id, []).append(obj) i greatfull point on how avoid it.
here's in situation:
posts = post.objects.filter(...)[:20] post_id_map = {} post in posts: post_id_map[post.id] = post # iteration causes queryset evaluated , cached. # can therefore annotate instances, e.g. custom `tag_list`. # note: don't assign `tags`, because result in update. post.tag_list = [] # we'll need relations between post , tag. # auto-generated model contains data `post.tags.through`. t in post.tags.through.select_related('tag').filter(post_id__in=post): post_id_map[t.post_id].tag_list.append(t.tag) # can iterate on `posts` again , use `tag_list` instead of `tags`. it nicer if pattern encapsulated somehow, might want add queryset method (e.g. select_tags()) you.
Comments
Post a Comment