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:

  1. get list of posts
  2. get list of tags used in posts
  3. 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

Popular posts from this blog

php - What is the difference between $_SERVER['PATH_INFO'] and $_SERVER['ORIG_PATH_INFO']? -

fortran - Function return type mismatch -

queue - mq_receive: message too long -