bgneal@399: """
bgneal@399: Common utility/helper code for the news app.
bgneal@399: 
bgneal@399: """
bgneal@399: from django.contrib.contenttypes.models import ContentType
bgneal@399: 
bgneal@399: from comments.models import Comment
bgneal@399: from tagging.models import TaggedItem
bgneal@399: from news.models import Story
bgneal@399: 
bgneal@399: 
bgneal@399: def attach_extra_attrs(stories):
bgneal@399:     """
bgneal@399:     For each story in the input stories list, attach 2 new attributes:
bgneal@399:     tag_list and comment_count. The tags and comment count info is pulled from
bgneal@399:     the database in bulk. This saves database queries when lots of news
bgneal@399:     stories are displayed at once. For best results, use ".defer('tags')"
bgneal@399:     when retrieve the stories from the database.
bgneal@399: 
bgneal@399:     """
bgneal@399:     stories_dict = dict((story.id, story) for story in stories)
bgneal@399:     story_ids = stories_dict.keys()
bgneal@399: 
bgneal@399:     # Get all the tags out in one query
bgneal@399:     ct = ContentType.objects.get_for_model(Story)
bgneal@399:     tagged_items = TaggedItem.objects.filter(content_type=ct,
bgneal@399:             object_id__in=story_ids).select_related('tag')
bgneal@399: 
bgneal@399:     for story in stories_dict.values():
bgneal@399:         story.tag_list = []
bgneal@399:         story.comment_count = 0
bgneal@399: 
bgneal@399:     # attach tags
bgneal@399:     for item in tagged_items:
bgneal@399:         stories_dict[item.object_id].tag_list.append(item.tag.name)
bgneal@399: 
bgneal@399:     # Now get all the comment counts out in one fell swoop
bgneal@399: 
bgneal@399:     story_ids = Comment.objects.filter(content_type=ct,
bgneal@399:             object_id__in=story_ids).values_list('object_id', flat=True)
bgneal@399: 
bgneal@399:     # compute comment_count
bgneal@399:     for story_id in story_ids:
bgneal@399:         stories_dict[story_id].comment_count += 1