Example #1
0
	def entry_tags(self):
		"""Returns a :class:`QuerySet` of :class:`.Tag`\ s that are used on any entries in this blog."""
		entry_pks = list(self.entries.values_list('pk', flat=True))
		kwargs = {
			'%s__object_id__in' % TaggedItem.tag_relname(): entry_pks
		}
		return TaggedItem.tags_for(BlogEntry).filter(**kwargs)
Example #2
0
def get_tag_cloud(model, queryset, tags_filter=None):
    if tags_filter is None:
        tags_filter = set()
        for item in queryset.all():
            tags_filter.update(item.tags.all())

    tags_filter = set([tag.id for tag in tags_filter])
    tags = set(TaggedItem.objects.filter(
        content_type__model=model.__name__.lower()
    ).values_list('tag_id', flat=True))

    if tags_filter is not None:
        tags = tags.intersection(tags_filter)
    tag_ids = list(tags)

    kwargs = TaggedItem.bulk_lookup_kwargs(queryset)
    kwargs['tag_id__in'] = tag_ids
    counted_tags = dict(TaggedItem.objects
                                  .filter(**kwargs)
                                  .values('tag')
                                  .annotate(count=models.Count('tag'))
                                  .values_list('tag', 'count'))
    tags = TaggedItem.tag_model().objects.filter(pk__in=counted_tags.keys())
    for tag in tags:
        tag.count = counted_tags[tag.pk]
    return sorted(tags, key=lambda x: -x.count)
Example #3
0
def get_tag_cloud(model, queryset, tags_filter=None):
    if tags_filter is None:
        tags_filter = set()
        for item in queryset.all():
            tags_filter.update(item.tags.all())

    tags_filter = set([tag.id for tag in tags_filter])
    tags = set(
        TaggedItem.objects.filter(
            content_type__model=model.__name__.lower()).values_list('tag_id',
                                                                    flat=True))

    if tags_filter is not None:
        tags = tags.intersection(tags_filter)
    tag_ids = list(tags)

    kwargs = TaggedItem.bulk_lookup_kwargs(queryset)
    kwargs['tag_id__in'] = tag_ids
    counted_tags = dict(
        TaggedItem.objects.filter(**kwargs).values('tag').annotate(
            count=models.Count('tag')).values_list('tag', 'count'))
    tags = TaggedItem.tag_model().objects.filter(pk__in=counted_tags.keys())
    for tag in tags:
        tag.count = counted_tags[tag.pk]
    return sorted(tags, key=lambda x: -x.count)
Example #4
0
def _delete_and_recreate_tags(slug):
    source_demo = Submission.objects.using("default").get(slug=slug)
    destination_demo = Submission.objects.using("new").get(slug=slug)
    source_type, destination_type = _get_demo_content_types()

    source_tags = source_demo.taggit_tags.all()
    source_tags_names = [tag.name for tag in source_tags]
    destination_tags = destination_demo.taggit_tags.using("new").all()
    destination_tags_names = [tag.name for tag in destination_tags]

    if source_tags_names == destination_tags_names:
        logger.info(
            "%s: Found %s matching tag(s): %s" % (source_demo.slug, len(destination_tags), destination_tags_names)
        )
        return destination_tags
    else:
        dest_demo_tagged_items = TaggedItem.objects.using("new").filter(
            tag__in=[tag for tag in destination_tags], object_id=destination_demo.id, content_type=destination_type
        )
        dest_demo_tagged_items.using("new").delete()
        logger.info("%s: Migrating %s tag(s): %s" % (source_demo.slug, len(source_tags), source_tags_names))
        for source_tag in source_tags:
            try:
                destination_tag = Tag.objects.using("new").get(name=source_tag.name)
            except Tag.DoesNotExist:
                destination_tag = Tag(name=source_tag.name)
                destination_tag.save(using="new")
            destination_demo_tag = TaggedItem(
                content_type=destination_type, object_id=destination_demo.id, tag=destination_tag
            )
            destination_demo_tag.save(using="new")
    return destination_tags
Example #5
0
def _delete_and_recreate_tags(slug):
    source_demo = Submission.objects.using('default').get(slug=slug)
    destination_demo = Submission.objects.using('new').get(slug=slug)
    source_type, destination_type = _get_demo_content_types()

    source_tags = source_demo.taggit_tags.all()
    source_tags_names = [tag.name for tag in source_tags]
    destination_tags = destination_demo.taggit_tags.using('new').all()
    destination_tags_names = [tag.name for tag in destination_tags]

    if source_tags_names == destination_tags_names:
        logger.info(
            "%s: Found %s matching tag(s): %s" %
            (source_demo.slug, len(destination_tags), destination_tags_names))
        return destination_tags
    else:
        dest_demo_tagged_items = TaggedItem.objects.using('new').filter(
            tag__in=[tag for tag in destination_tags],
            object_id=destination_demo.id,
            content_type=destination_type)
        dest_demo_tagged_items.using('new').delete()
        logger.info("%s: Migrating %s tag(s): %s" %
                    (source_demo.slug, len(source_tags), source_tags_names))
        for source_tag in source_tags:
            try:
                destination_tag = (Tag.objects.using('new').get(
                    name=source_tag.name))
            except Tag.DoesNotExist:
                destination_tag = Tag(name=source_tag.name)
                destination_tag.save(using='new')
            destination_demo_tag = TaggedItem(content_type=destination_type,
                                              object_id=destination_demo.id,
                                              tag=destination_tag)
            destination_demo_tag.save(using='new')
    return destination_tags
Example #6
0
    def get_context_data(self, **kwargs):
        context = super(BlogBaseView, self).get_context_data(**kwargs)
        context['blog_tags'] = TaggedItem.tags_for(Blog).order_by('name')
        context['recent_blog_list'] = Blog.objects.recent_posts()
        # context['blog_list'] = Blog.objects.all()

        return context
Example #7
0
 def set_taggeditems(self):
     objects = OldTaggedItem.objects.all()
     print objects.count()
     for old_tagitem in objects:
         old_id = old_tagitem.tag_id
         new_id = self.dupemap.get(old_id, old_id)
         new_tags = NewTag.objects.filter(id=new_id)
         if new_tags:
             new_tag = new_tags[0]
             new_tagitem = NewTaggedItem(
                     id=old_tagitem.id, 
                     tag=new_tag,
                     content_type=old_tagitem.content_type,
                     object_id=old_tagitem.object_id)
             new_tagitem.save()
     print NewTaggedItem.objects.count()
Example #8
0
 def handle(self, *arg, **kwargs):
     print '##########################################################'
     print '### This file is generated by ./manage.py dump_topics. ###'
     print '##########################################################'
     print 'from django.utils.translation import pgettext\n'
     for tag in TaggedItem.tags_for(Document):
         print 'pgettext("KB Topic", """{tag}""")'.format(tag=tag.name)
Example #9
0
 def handle(self, *arg, **kwargs):
     print '##########################################################'
     print '### This file is generated by ./manage.py dump_topics. ###'
     print '##########################################################'
     print 'from tower import ugettext as _\n'
     for tag in TaggedItem.tags_for(Document):
         print '_("""{tag}""", "KB Topic")'.format(tag=tag.name)
Example #10
0
 def done(self, form_list, form_dict, **kw):
     """Overriden to do a job"""
     options = self.get_options()
     data = {}
     for f in form_list:
         data.update(f.cleaned_data)
     data.update(self.request.session[options['session_prefix']])
     content_type = ContentType.objects.get_by_natural_key(data['app_label'], data['model'])
     ids = data['ids']
     model = content_type.model_class()
     objs = model.objects.filter(pk__in=ids)
     ids = list(objs.values_list('pk', flat=True))
     cnt = len(ids)
     tags = [Tag.objects.get_or_create(name=t)[0] for t in data['tags']]
     existent = TaggedItem.objects.filter(tag__in=tags, content_type=content_type, object_id__in=ids)
     if data['clear']:
         existent.delete()
         messages.add_message(self.request, messages.INFO, _("Untagged %(number)s %(model_name)s") % {
             "number": cnt,
             "model_name": model_ngettext(model._meta, cnt)
         })
     else:
         existent_tags = set([(e.tag_id, e.object_id) for e in existent])
         tagged_items = [
             TaggedItem(tag=tag, content_type=content_type, object_id=o.id)
             for o in objs for tag in tags if not (tag.id, o.id) in existent_tags
         ]
         TaggedItem.objects.bulk_create(tagged_items)
         messages.add_message(self.request, messages.INFO, _("Tagged %(number)s %(model_name)s") % {
             "number": cnt,
             "model_name": model_ngettext(model._meta, cnt)
         })
     return HttpResponseRedirect(data['referer'])
Example #11
0
 def tag_cloud(self, other_model=None, queryset=None, published=True):
     from taggit.models import TaggedItem
     tag_ids = self._taglist(other_model, queryset)
     kwargs = {}
     if published:
         kwargs = TaggedItem.bulk_lookup_kwargs(self.model.objects.published())
     kwargs['tag_id__in'] = tag_ids
     counted_tags = dict(TaggedItem.objects
                                   .filter(**kwargs)
                                   .values('tag')
                                   .annotate(count=models.Count('tag'))
                                   .values_list('tag', 'count'))
     tags = TaggedItem.tag_model().objects.filter(pk__in=counted_tags.keys())
     for tag in tags:
         tag.count = counted_tags[tag.pk]
     return sorted(tags, key=lambda x: -x.count)
Example #12
0
    def get_tags(self, request, namespace):
        """
        Get tags with articles count for given namespace string.

        Return list of Tag objects ordered by custom 'num_articles' attribute.
        """
        if (request and hasattr(request, 'toolbar') and
                request.toolbar and request.toolbar.edit_mode):
            articles = self.namespace(namespace)
        else:
            articles = self.published().namespace(namespace)
        if not articles:
            # return empty iterable early not to perform useless requests
            return []
        kwargs = TaggedItem.bulk_lookup_kwargs(articles)

        # aggregate and sort
        counted_tags = dict(TaggedItem.objects
                            .filter(**kwargs)
                            .values('tag')
                            .annotate(tag_count=models.Count('tag'))
                            .values_list('tag', 'tag_count'))

        # and finally get the results
        tags = Tag.objects.filter(pk__in=counted_tags.keys())
        for tag in tags:
            tag.num_articles = counted_tags[tag.pk]
        return sorted(tags, key=attrgetter('num_articles'), reverse=True)
Example #13
0
    def tag_cloud(self,
                  other_model=None,
                  queryset=None,
                  published=True,
                  on_site=False):
        from taggit.models import TaggedItem

        if on_site:
            queryset = queryset.on_site()
        tag_ids = self._taglist(other_model, queryset)
        kwargs = {}
        if published:
            kwargs = {
                "object_id__in": self.model.objects.published(),
                "content_type": ContentType.objects.get_for_model(self.model),
            }
        kwargs["tag_id__in"] = tag_ids
        counted_tags = dict(
            TaggedItem.objects.filter(**kwargs).values("tag").annotate(
                count=models.Count("tag")).values_list("tag", "count"))
        tags = TaggedItem.tag_model().objects.filter(
            pk__in=counted_tags.keys())
        for tag in tags:
            tag.count = counted_tags[tag.pk]
        return sorted(tags, key=lambda x: -x.count)
Example #14
0
    def get_tags(self, entries=None, language=None):
        """Returns tags used to tag post and its count. Results are ordered by count."""

        if not entries:
            entries = self

        if language:
            entries = entries.filter_by_language(language)
        entries = entries.distinct()
        if not entries:
            return []
        kwargs = TaggedItem.bulk_lookup_kwargs(entries)

        # aggregate and sort
        counted_tags = dict(TaggedItem.objects
                                      .filter(**kwargs)
                                      .values('tag')
                                      .annotate(count=models.Count('tag'))
                                      .values_list('tag', 'count'))

        # and finally get the results
        tags = Tag.objects.filter(pk__in=counted_tags.keys())
        for tag in tags:
            tag.count = counted_tags[tag.pk]
        return sorted(tags, key=lambda x: -x.count)
Example #15
0
 def tag_cloud(self, other_model=None, queryset=None, published=True):
     from taggit.models import TaggedItem
     tag_ids = self._taglist(other_model, queryset)
     kwargs = {}
     if published:
         kwargs = TaggedItem.bulk_lookup_kwargs(self.model.objects.published())
     kwargs['tag_id__in'] = tag_ids
     counted_tags = dict(TaggedItem.objects
                                   .filter(**kwargs)
                                   .values('tag')
                                   .annotate(count=models.Count('tag'))
                                   .values_list('tag', 'count'))
     tags = TaggedItem.tag_model().objects.filter(pk__in=counted_tags.keys())
     for tag in tags:
         tag.count = counted_tags[tag.pk]
     return sorted(tags, key=lambda x: -x.count)
Example #16
0
    def get_tags(self, request, namespace):
        """
        Get tags with articles count for given namespace string.

        Return list of Tag objects ordered by custom 'num_articles' attribute.
        """
        if (request and hasattr(request, 'toolbar') and request.toolbar
                and request.toolbar.edit_mode):
            articles = self.namespace(namespace)
        else:
            articles = self.published().namespace(namespace)
        if not articles:
            # return empty iterable early not to perform useless requests
            return []
        kwargs = TaggedItem.bulk_lookup_kwargs(articles)

        # aggregate and sort
        counted_tags = dict(
            TaggedItem.objects.filter(**kwargs).values('tag').annotate(
                tag_count=models.Count('tag')).values_list('tag', 'tag_count'))

        # and finally get the results
        tags = Tag.objects.filter(pk__in=counted_tags.keys())
        for tag in tags:
            tag.num_articles = counted_tags[tag.pk]
        return sorted(tags, key=attrgetter('num_articles'), reverse=True)
Example #17
0
    def extract_document(cls, obj_id):
        """Extracts indexable attributes from a Question and its answers."""

        # Note: Need to keep this in sync with
        # tasks.update_question_vote_chunk.
        obj = cls.uncached.values(
            'id', 'title', 'content', 'num_answers', 'solution_id',
            'is_locked', 'created', 'updated', 'num_votes_past_week',
            'creator__username').get(pk=obj_id)

        d = {}
        d['id'] = obj['id']
        d['model'] = cls.get_model_name()
        d['title'] = obj['title']
        d['question_content'] = obj['content']
        d['num_answers'] = obj['num_answers']
        d['is_solved'] = bool(obj['solution_id'])
        d['is_locked'] = obj['is_locked']
        d['has_answers'] = bool(obj['num_answers'])

        # We do this because get_absolute_url is an instance method
        # and we don't want to create an instance because it's a DB
        # hit and expensive. So we do it by hand. get_absolute_url
        # doesn't change much, so this is probably ok.
        d['url'] = reverse('questions.answers',
                           kwargs={'question_id': obj['id']})

        # TODO: Sphinx stores created and updated as seconds since the
        # epoch, so we convert them to that format here so that the
        # search view works correctly. When we ditch Sphinx, we should
        # see if it's faster to filter on ints or whether we should
        # switch them to dates.
        d['created'] = int(time.mktime(obj['created'].timetuple()))
        d['updated'] = int(time.mktime(obj['updated'].timetuple()))

        d['question_creator'] = obj['creator__username']
        d['num_votes'] = (QuestionVote.objects
                          .filter(question=obj['id'])
                          .count())
        d['num_votes_past_week'] = obj['num_votes_past_week']

        d['tag'] = list(TaggedItem.tags_for(
            Question, Question(pk=obj_id)).values_list('name', flat=True))

        answer_values = list(Answer.objects
                                   .filter(question=obj_id)
                                   .values_list('content',
                                                'creator__username'))

        d['answer_content'] = [a[0] for a in answer_values]
        d['answer_creator'] = list(set([a[1] for a in answer_values]))

        if not answer_values:
            d['has_helpful'] = False
        else:
            d['has_helpful'] = Answer.objects.filter(
                question=obj_id).filter(votes__helpful=True).exists()

        d['indexed_on'] = int(time.time())
        return d
Example #18
0
 def userfeed_tags(user):
     '''Return all the UserFeed tags for a user.'''
     #ct = ContentType.objects.get_for_model(UserFeed)
     kwargs = {
         "userfeed__in": UserFeed.objects.filter(user=user)
     }
     tags = TaggedItem.tag_model().objects.filter(**kwargs).distinct()
     return tags
Example #19
0
def view_questions(request, questions_template):
    questions_count = Question.objects.count()
    #FIXME/TODO:This has to be cached at all costs
    all_tags = TaggedItem.tags_for(Question)
    return response(request, questions_template, {
        'questions_count': questions_count,
        'all_tags': all_tags
    })
 def set_taggeditems(self):
     objects = OldTaggedItem.objects.all()
     print objects.count()
     for old_tagitem in objects:
         old_id = old_tagitem.tag_id
         new_id = self.dupemap.get(old_id, old_id)
         new_tags = NewTag.objects.filter(id=new_id)
         if new_tags:
             new_tag = new_tags[0]
             new_tagitem = NewTaggedItem(
                 id=old_tagitem.id,
                 tag=new_tag,
                 content_type=old_tagitem.content_type,
                 object_id=old_tagitem.object_id,
             )
             new_tagitem.save()
     print NewTaggedItem.objects.count()
Example #21
0
 def read(cls, req, slug=None, model=None):
     if model:
         models = [System, Module, Interface, ArchitecturalPattern]
         lookup = dict(zip(map(lambda model: model._meta.object_name.lower(), models), models))
         return TaggedItem.tags_for(lookup[model])
     if slug:
         return map(lambda i: i.content_object, TaggedItem.objects.select_related().filter(tag=Tag.objects.get(slug=slug)))
     else:
         return map(lambda i: dict(name=i['name'], count=i['count'], resource_uri=reverse('api_tag', args=[i['slug']])), Tag.objects.values('name', 'slug').annotate(count=Count('taggit_taggeditem_items')).order_by('-count'))
Example #22
0
 def clean(self):
     data = self.cleaned_data
     if data['auto']:
         tags = set(data['tags'])
         tags.update([
             tag
             for tag in TaggedItem.tags_for(models.Post)
             if re.search(r'\b%s\b' % tag.name, data['content'], re.I|re.M)
         ])
         data['tags'] = list(tags)
     return data
Example #23
0
 def lookups(self, request, model_admin):
   """
   Returns a list of tuples. The first element in each tuple is the coded value
   for the option that will appear in the URL query. The second element is the
   human-readable name for the option that will appear in the right sidebar.
   """
   list = []
   tags = TaggedItem.tags_for(model_admin.model)
   for tag in tags:
     list.append( (tag.name, _(tag.name)) )
   return list    
Example #24
0
 def lookups(self, request, model_admin):
   """
   Returns a list of tuples. The first element in each tuple is the coded value
   for the option that will appear in the URL query. The second element is the
   human-readable name for the option that will appear in the right sidebar.
   """
   list = []
   tags = TaggedItem.tags_for(model_admin.model)
   for tag in tags:
     list.append( (tag.name, (tag.name)) )
   return list
    def lookups(self, request, model_admin):
        """
        Returns tuple of tuples (key, value) for available Tag choices.

        :param request: the Request instance.
        :param model_admin: the ModelAdmin instance.
        :rtype: tuple.
        """
        return (
            (tag.id, tag.name)
            for tag in TaggedItem.tags_for(Ticket)
        )
Example #26
0
 def get_context_data(self, **kwargs):
     query = self.request.GET.get('query', None)
     if query is None:
         return {'tags': []}
     filter = {}
     if len(query) > 3:
         filter['name__icontains'] = query
     else:
         filter['name__istartswith'] = query
     tags = TaggedItem.tags_for(Icon).filter(**filter).order_by('name')
     return {
         'tags': [t.name for t in tags]
     }
 def forwards(self, orm):
     for entry in orm['checklists.Entry'].objects.all():
         tags = TaggedItem.tags_for(orm['checklists.Entry'], entry)
         for label in [unicode(tag) for tag in tags]:
             names = {}
             # Add localized fields for the SpeciesGroup table
             for language_code, language_name in settings.LANGUAGES:
                 if settings.LANGUAGE_CODE == language_code:
                     names['name_%s' % language_code] = label.capitalize()
                 else:
                     names['name_%s' % language_code] = ''
             tag, created = orm['checklists.EntryTag'].objects.get_or_create(
                 slug=label.lower(),
                 **names
             )
             entry.tags.add(tag)
Example #28
0
    def extract_document(cls, obj_id):
        """Extracts indexable attributes from a Question and its answers."""
        obj = cls.uncached.values(
            "id",
            "title",
            "content",
            "num_answers",
            "solution_id",
            "is_locked",
            "created",
            "updated",
            "num_votes_past_week",
            "creator__username",
        ).get(pk=obj_id)

        d = {}
        d["id"] = obj["id"]
        d["title"] = obj["title"]
        d["question_content"] = obj["content"]
        d["replies"] = obj["num_answers"]
        d["is_solved"] = bool(obj["solution_id"])
        d["is_locked"] = obj["is_locked"]
        d["has_answers"] = bool(obj["num_answers"])

        # TODO: Sphinx stores created and updated as seconds since the
        # epoch, so we convert them to that format here so that the
        # search view works correctly. When we ditch Sphinx, we should
        # see if it's faster to filter on ints or whether we should
        # switch them to dates.
        d["created"] = int(time.mktime(obj["created"].timetuple()))
        d["updated"] = int(time.mktime(obj["updated"].timetuple()))

        d["question_creator"] = obj["creator__username"]
        d["question_votes"] = obj["num_votes_past_week"]

        d["tag"] = list(TaggedItem.tags_for(Question, Question(pk=obj_id)).values_list("name", flat=True))

        answer_values = list(Answer.objects.filter(question=obj_id).values_list("content", "creator__username"))
        d["answer_content"] = [a[0] for a in answer_values]
        d["answer_creator"] = list(set([a[1] for a in answer_values]))

        if not answer_values:
            d["has_helpful"] = False
        else:
            d["has_helpful"] = Answer.objects.filter(question=obj_id).filter(votes__helpful=True).exists()

        return d
Example #29
0
def view_tagged_questions(request, tag_name, tagged_questions_template):
    tag = get_object_or_404(Tag, name=tag_name)
    questions = Question.objects.filter(tags__name__in=[tag_name]).values('id', 'slug', 'title')
    paginator = Paginator(questions, settings.DEFAULT_PAGINATION_COUNT)
    try:
        page = int(request.GET.get('page', 1))
    except ValueError:
        page = 1
    try:
        questions = paginator.page(page)
    except (EmptyPage, InvalidPage):
        questions = paginator.page(paginator.num_pages)
    #FIXME/TODO:This has to be cached at all costs
    all_tags = TaggedItem.tags_for(Question)
    return response(request, tagged_questions_template, {'questions': questions.object_list,
                                                        'tag': tag,
                                                        'all_tags':all_tags})
Example #30
0
def _add_tags(obj, tags_str, creator, content_type_name):
    for tag_name in tags_str.split(','):
        tag_name = tag_name.strip()
        # don't recreate the tag if it already exists
        try:
            t = Tag.objects.get(slug=slugify(tag_name))
        except ObjectDoesNotExist as dne:
            t = Tag()
            t.name = tag_name[:99]
            t.slug = slugify(tag_name)
            t.save()
        ti = TaggedItem()
        ti.tag = t
        ti.object_id = obj.id
        ti.tag_creator = creator
        ti.content_type = ContentType.objects.filter(name=content_type_name)[0]
        ti.save()
Example #31
0
    def get_tags(self, language):
        """Returns tags used to tag post and its count. Results are ordered by count."""

        # get tagged post
        entries = self.filter_by_language(language).distinct()
        if not entries:
            return []
        kwargs = TaggedItem.bulk_lookup_kwargs(entries)

        # aggregate and sort
        counted_tags = dict(
            TaggedItem.objects.filter(**kwargs).values('tag').annotate(
                count=models.Count('tag')).values_list('tag', 'count'))

        # and finally get the results
        tags = Tag.objects.filter(pk__in=counted_tags.keys())
        for tag in tags:
            tag.count = counted_tags[tag.pk]
        return sorted(tags, key=lambda x: -x.count)
Example #32
0
def view_tagged_questions(request, tag_name, tagged_questions_template):
    tag = get_object_or_404(Tag, name=tag_name)
    questions = Question.objects.filter(tags__name__in=[tag_name]).values(
        'id', 'slug', 'title')
    paginator = Paginator(questions, settings.DEFAULT_PAGINATION_COUNT)
    try:
        page = int(request.GET.get('page', 1))
    except ValueError:
        page = 1
    try:
        questions = paginator.page(page)
    except (EmptyPage, InvalidPage):
        questions = paginator.page(paginator.num_pages)
    #FIXME/TODO:This has to be cached at all costs
    all_tags = TaggedItem.tags_for(Question)
    return response(request, tagged_questions_template, {
        'questions': questions.object_list,
        'tag': tag,
        'all_tags': all_tags
    })
Example #33
0
    def get_tags(self, namespace):
        """
        Get tags with articles count for given namespace string.

        Returns list of Tag objects with ordered by custom 'num_entries' attribute.
        """

        entries = self.filter(app_config__namespace=namespace)
        if not entries:
            return []
        kwargs = TaggedItem.bulk_lookup_kwargs(entries)

        # aggregate and sort
        counted_tags = dict(
            TaggedItem.objects.filter(**kwargs).values('tag').annotate(
                tag_count=models.Count('tag')).values_list('tag', 'tag_count'))

        # and finally get the results
        tags = Tag.objects.filter(pk__in=counted_tags.keys())
        for tag in tags:
            tag.num_entries = counted_tags[tag.pk]
        return sorted(tags, key=attrgetter('num_entries'), reverse=True)
Example #34
0
    def lookups(self, request, model_admin):
        t = list()
        for i in TaggedItem.tags_for(model_admin.model):
            t.append((i.slug, i.name))

        return t
Example #35
0
    def extract_document(cls, obj_id, obj=None):
        """Extracts indexable attributes from a Question and its answers."""
        fields = ['id', 'title', 'content', 'num_answers', 'solution_id',
                  'is_locked', 'is_archived', 'created', 'updated',
                  'num_votes_past_week', 'locale', 'product_id', 'topic_id',
                  'is_spam']
        composed_fields = ['creator__username']
        all_fields = fields + composed_fields

        if obj is None:
            # Note: Need to keep this in sync with
            # tasks.update_question_vote_chunk.
            model = cls.get_model()
            obj = model.objects.values(*all_fields).get(pk=obj_id)
        else:
            fixed_obj = dict([(field, getattr(obj, field))
                              for field in fields])
            fixed_obj['creator__username'] = obj.creator.username
            obj = fixed_obj

        if obj['is_spam']:
            raise UnindexMeBro()

        d = {}
        d['id'] = obj['id']
        d['model'] = cls.get_mapping_type_name()

        # We do this because get_absolute_url is an instance method
        # and we don't want to create an instance because it's a DB
        # hit and expensive. So we do it by hand. get_absolute_url
        # doesn't change much, so this is probably ok.
        d['url'] = reverse('questions.details',
                           kwargs={'question_id': obj['id']})

        d['indexed_on'] = int(time.time())

        d['created'] = int(time.mktime(obj['created'].timetuple()))
        d['updated'] = int(time.mktime(obj['updated'].timetuple()))

        topics = Topic.objects.filter(id=obj['topic_id'])
        products = Product.objects.filter(id=obj['product_id'])
        d['topic'] = [t.slug for t in topics]
        d['product'] = [p.slug for p in products]

        d['question_title'] = obj['title']
        d['question_content'] = obj['content']
        d['question_num_answers'] = obj['num_answers']
        d['question_is_solved'] = bool(obj['solution_id'])
        d['question_is_locked'] = obj['is_locked']
        d['question_is_archived'] = obj['is_archived']
        d['question_has_answers'] = bool(obj['num_answers'])

        d['question_creator'] = obj['creator__username']
        d['question_num_votes'] = (QuestionVote.objects
                                               .filter(question=obj['id'])
                                               .count())
        d['question_num_votes_past_week'] = obj['num_votes_past_week']

        d['question_tag'] = list(TaggedItem.tags_for(
            Question, Question(pk=obj_id)).values_list('name', flat=True))

        d['question_locale'] = obj['locale']

        answer_values = list(Answer.objects
                                   .filter(question=obj_id, is_spam=False)
                                   .values_list('content',
                                                'creator__username'))

        d['question_answer_content'] = [a[0] for a in answer_values]
        d['question_answer_creator'] = list(set(a[1] for a in answer_values))

        if not answer_values:
            d['question_has_helpful'] = False
        else:
            d['question_has_helpful'] = Answer.objects.filter(
                question=obj_id).filter(votes__helpful=True).exists()

        return d
Example #36
0
 def get_queryset(self):
     return TaggedItem.tags_for(Post)
Example #37
0
def tags_used_for_submissions():
    return TaggedItem.tags_for(Submission)
Example #38
0
    def extract_document(cls, obj_id, obj=None):
        """Extracts indexable attributes from a Question and its answers."""
        fields = ['id', 'title', 'content', 'num_answers', 'solution_id',
                  'is_locked', 'is_archived', 'created', 'updated',
                  'num_votes_past_week', 'locale', 'product_id', 'topic_id',
                  'is_spam']
        composed_fields = ['creator__username']
        all_fields = fields + composed_fields

        if obj is None:
            # Note: Need to keep this in sync with
            # tasks.update_question_vote_chunk.
            model = cls.get_model()
            obj = model.objects.values(*all_fields).get(pk=obj_id)
        else:
            fixed_obj = dict([(field, getattr(obj, field))
                              for field in fields])
            fixed_obj['creator__username'] = obj.creator.username
            obj = fixed_obj

        if obj['is_spam']:
            raise UnindexMeBro()

        d = {}
        d['id'] = obj['id']
        d['model'] = cls.get_mapping_type_name()

        # We do this because get_absolute_url is an instance method
        # and we don't want to create an instance because it's a DB
        # hit and expensive. So we do it by hand. get_absolute_url
        # doesn't change much, so this is probably ok.
        d['url'] = reverse('questions.details',
                           kwargs={'question_id': obj['id']})

        d['indexed_on'] = int(time.time())

        d['created'] = int(time.mktime(obj['created'].timetuple()))
        d['updated'] = int(time.mktime(obj['updated'].timetuple()))

        topics = Topic.objects.filter(id=obj['topic_id'])
        products = Product.objects.filter(id=obj['product_id'])
        d['topic'] = [t.slug for t in topics]
        d['product'] = [p.slug for p in products]

        d['question_title'] = obj['title']
        d['question_content'] = obj['content']
        d['question_num_answers'] = obj['num_answers']
        d['question_is_solved'] = bool(obj['solution_id'])
        d['question_is_locked'] = obj['is_locked']
        d['question_is_archived'] = obj['is_archived']
        d['question_has_answers'] = bool(obj['num_answers'])

        d['question_creator'] = obj['creator__username']
        d['question_num_votes'] = (QuestionVote.objects
                                               .filter(question=obj['id'])
                                               .count())
        d['question_num_votes_past_week'] = obj['num_votes_past_week']

        d['question_tag'] = list(TaggedItem.tags_for(
            Question, Question(pk=obj_id)).values_list('name', flat=True))

        d['question_locale'] = obj['locale']

        answer_values = list(Answer.objects
                                   .filter(question=obj_id, is_spam=False)
                                   .values_list('content',
                                                'creator__username'))

        d['question_answer_content'] = [a[0] for a in answer_values]
        d['question_answer_creator'] = list(set(a[1] for a in answer_values))

        if not answer_values:
            d['question_has_helpful'] = False
        else:
            d['question_has_helpful'] = Answer.objects.filter(
                question=obj_id).filter(votes__helpful=True).exists()

        return d
Example #39
0
def message_log(req, context={}, template="messagelog/index.html"):
    messages = Message.objects.all()
    if 'messages_qs' in context:
        messages = context['messages_qs']
    contact = None
    search = None
    show_advanced_filter = None # "Y" to show the advanced filter, "N" to hide it
    all_tags = []               # A distinct list of all tags pertaining to any Messages in the Message Log
    selected_tags = None        # The tags selected by the user by which to filter the Messages
    tag_filter_flag = None      # "Y" if the user chose to do tag filtering, "N" otherwise
    tag_filter_style = None     # Tag filtering style: "any" to show Messages which match any of the selected_tags,
                                #                      "all" to show Messages which match all of the selected tags
    if 'contact' in req.GET:
        if req.GET['contact'] == '':
            contact=None
        else:
            contact = Contact.objects.get(pk=req.GET['contact'])
            messages = messages.filter(contact=contact)

    if 'search' in req.GET and req.GET['search'] != '':
        search = req.GET['search']
        safe_search = re.escape(search.strip("'\""))
        messages = messages.filter(Q(text__iregex=safe_search) |\
                                   Q(connection__identity__iregex=safe_search))

    # Extract and sort all tag names
    for tag in TaggedItem.tags_for(Message):
        all_tags.append(tag.name)
    all_tags.sort()

    # Retrieve list of selected tags (default to empty list)
    if "selected_tags" in req.GET:
        selected_tags = req.GET.getlist("selected_tags")
    else:
        selected_tags = []

    # Retrieve tag filter flag (default to "N")
    if "tag_filter_flag" in req.GET and req.GET["tag_filter_flag"] == "Y":
        tag_filter_flag = req.GET["tag_filter_flag"]
    else:
        tag_filter_flag = "N"

    # Retrieve advanced filter flag
    if ("show_advanced_filter" in req.GET and req.GET["show_advanced_filter"] == "Y") or (tag_filter_flag == "Y"):
        show_advanced_filter = "Y"
    else:
        show_advanced_filter = "N"

    # Retrieve tag filter style (default to "any")
    if "tag_filter_style" in req.GET and req.GET["tag_filter_style"] == "all":
        tag_filter_style = req.GET["tag_filter_style"]
    else:
        tag_filter_style = "any"

    # If no tags were selected, automatically disable tag filtering
    if len(selected_tags) == 0:
        tag_filter_flag = "N"

    # If the user chose to do tag filtering, perform the filter now
    if tag_filter_flag == "Y":
        if tag_filter_style == "all":
            for tag_name in selected_tags:
                messages = messages.filter(tags__name__in=[tag_name])
        else:
            messages = messages.filter(tags__name__in=selected_tags).distinct()
    context.update({
            "messages_table": MessageTable(messages, request=req),
            "search": search,
            "contact": contact,
            "contacts": Contact.objects.all().order_by("name"),
            "show_advanced_filter": show_advanced_filter,
            "all_tags": all_tags,
            "selected_tags": selected_tags,
            "tag_filter_flag": tag_filter_flag,
            "tag_filter_style": tag_filter_style
    })
    return render_to_response(
        template, context, context_instance=RequestContext(req)
    )
 def lookups(self, request, model_admin):
     model_tags = [tag.name for tag in
         TaggedItem.tags_for(model_admin.model)]
     model_tags.sort()
     return tuple([(tag, tag) for tag in model_tags])
Example #41
0
 def lookups(self, request, model_admin):
     model_tags = [
         tag.name for tag in TaggedItem.tags_for(model_admin.model)
     ]
     model_tags.sort()
     return tuple([(tag, tag) for tag in model_tags])
Example #42
0
 def categories(self):
     return TaggedItem.tags_for(Post)
Example #43
0
    def extract_document(cls, obj_id, obj=None):
        """Extracts indexable attributes from a Question and its answers."""
        fields = ['id', 'title', 'content', 'num_answers', 'solution_id',
                  'is_locked', 'created', 'updated', 'num_votes_past_week',
                  'locale']
        composed_fields = ['creator__username']
        all_fields = fields + composed_fields

        if obj is None:
            # Note: Need to keep this in sync with
            # tasks.update_question_vote_chunk.
            obj = cls.uncached.values(*all_fields).get(pk=obj_id)
        else:
            fixed_obj = dict([(field, getattr(obj, field))
                              for field in fields])
            fixed_obj['creator__username'] = obj.creator.username
            obj = fixed_obj

        d = {}
        d['id'] = obj['id']
        d['document_id'] = cls.get_document_id(obj['id'])
        d['model'] = cls.get_model_name()

        # We do this because get_absolute_url is an instance method
        # and we don't want to create an instance because it's a DB
        # hit and expensive. So we do it by hand. get_absolute_url
        # doesn't change much, so this is probably ok.
        d['url'] = reverse('questions.answers',
                           kwargs={'question_id': obj['id']})

        d['indexed_on'] = int(time.time())

        # TODO: Sphinx stores created and updated as seconds since the
        # epoch, so we convert them to that format here so that the
        # search view works correctly. When we ditch Sphinx, we should
        # see if it's faster to filter on ints or whether we should
        # switch them to dates.
        d['created'] = int(time.mktime(obj['created'].timetuple()))
        d['updated'] = int(time.mktime(obj['updated'].timetuple()))

        topics = Topic.uncached.filter(question__id=obj['id'])
        products = Product.uncached.filter(question__id=obj['id'])
        d['topic'] = [t.slug for t in topics]
        d['product'] = [p.slug for p in products]

        d['question_title'] = obj['title']
        d['question_content'] = obj['content']
        d['question_num_answers'] = obj['num_answers']
        d['question_is_solved'] = bool(obj['solution_id'])
        d['question_is_locked'] = obj['is_locked']
        d['question_has_answers'] = bool(obj['num_answers'])

        d['question_creator'] = obj['creator__username']
        d['question_num_votes'] = (QuestionVote.objects
                          .filter(question=obj['id'])
                          .count())
        d['question_num_votes_past_week'] = obj['num_votes_past_week']

        d['question_tag'] = list(TaggedItem.tags_for(
            Question, Question(pk=obj_id)).values_list('name', flat=True))

        d['question_locale'] = obj['locale']

        answer_values = list(Answer.objects
                                   .filter(question=obj_id)
                                   .values_list('content',
                                                'creator__username'))

        d['question_answer_content'] = [a[0] for a in answer_values]
        d['question_answer_creator'] = list(set(a[1] for a in answer_values))

        if not answer_values:
            d['question_has_helpful'] = False
        else:
            d['question_has_helpful'] = Answer.objects.filter(
                question=obj_id).filter(votes__helpful=True).exists()

        return d
Example #44
0
def tags_used_for_submissions():
    return TaggedItem.tags_for(Submission)
Example #45
0
def message_log(req, context={}, template="messagelog/index.html"):
    messages = Message.objects.all()
    if 'messages_qs' in context:
        messages = context['messages_qs']
    contact = None
    search = None
    show_advanced_filter = None  # "Y" to show the advanced filter, "N" to hide it
    all_tags = [
    ]  # A distinct list of all tags pertaining to any Messages in the Message Log
    selected_tags = None  # The tags selected by the user by which to filter the Messages
    tag_filter_flag = None  # "Y" if the user chose to do tag filtering, "N" otherwise
    tag_filter_style = None  # Tag filtering style: "any" to show Messages which match any of the selected_tags,
    #                      "all" to show Messages which match all of the selected tags
    if 'contact' in req.GET:
        if req.GET['contact'] == '':
            contact = None
        else:
            contact = Contact.objects.get(pk=req.GET['contact'])
            messages = messages.filter(contact=contact)

    if 'search' in req.GET and req.GET['search'] != '':
        search = req.GET['search']
        safe_search = re.escape(search.strip("'\""))
        messages = messages.filter(Q(text__iregex=safe_search) |\
                                   Q(connection__identity__iregex=safe_search))

    # Extract and sort all tag names
    for tag in TaggedItem.tags_for(Message):
        all_tags.append(tag.name)
    all_tags.sort()

    # Retrieve list of selected tags (default to empty list)
    if "selected_tags" in req.GET:
        selected_tags = req.GET.getlist("selected_tags")
    else:
        selected_tags = []

    # Retrieve tag filter flag (default to "N")
    if "tag_filter_flag" in req.GET and req.GET["tag_filter_flag"] == "Y":
        tag_filter_flag = req.GET["tag_filter_flag"]
    else:
        tag_filter_flag = "N"

    # Retrieve advanced filter flag
    if ("show_advanced_filter" in req.GET
            and req.GET["show_advanced_filter"] == "Y") or (tag_filter_flag
                                                            == "Y"):
        show_advanced_filter = "Y"
    else:
        show_advanced_filter = "N"

    # Retrieve tag filter style (default to "any")
    if "tag_filter_style" in req.GET and req.GET["tag_filter_style"] == "all":
        tag_filter_style = req.GET["tag_filter_style"]
    else:
        tag_filter_style = "any"

    # If no tags were selected, automatically disable tag filtering
    if len(selected_tags) == 0:
        tag_filter_flag = "N"

    # If the user chose to do tag filtering, perform the filter now
    if tag_filter_flag == "Y":
        if tag_filter_style == "all":
            for tag_name in selected_tags:
                messages = messages.filter(tags__name__in=[tag_name])
        else:
            messages = messages.filter(tags__name__in=selected_tags).distinct()
    context.update({
        "messages_table": MessageTable(messages, request=req),
        "search": search,
        "contact": contact,
        "contacts": Contact.objects.all().order_by("name"),
        "show_advanced_filter": show_advanced_filter,
        "all_tags": all_tags,
        "selected_tags": selected_tags,
        "tag_filter_flag": tag_filter_flag,
        "tag_filter_style": tag_filter_style
    })
    return render_to_response(template,
                              context,
                              context_instance=RequestContext(req))
Example #46
0
def view_questions(request, questions_template):
    questions_count = Question.objects.count()
    #FIXME/TODO:This has to be cached at all costs
    all_tags = TaggedItem.tags_for(Question)
    return response(request, questions_template, {'questions_count':questions_count,
                                                  'all_tags':all_tags})
def focus(request, field, value, template_name="tasks/focus.html"):
    
    group, bridge = group_and_bridge(request)
    if group:
        is_member = group.request.user_is_member()
    else:
        is_member = True
    
    group_by = request.GET.get("group_by")
    filter_only = request.GET.get("filter_only", False)
    tags_list = []
    expanded_tags_list = []
    
    if group:
        tasks = group.content_objects(Task)
    else:
        tasks = Task.objects.filter(object_id=None)
    
    # default filtering
    state_keys = dict(workflow.STATE_CHOICES).keys()
    default_states = set(state_keys).difference(
        # don't show these states
        set(["2", "3"])
    )
    
    # have to store for each prefix because initial data isn't support on the
    # FilterSet
    filter_data = {
        "state": list(default_states),
    }
    filter_data.update(request.GET)
    
    task_filter = TaskFilter(filter_data, queryset=tasks)
    
    if field == "modified":
        try:
            # @@@ this seems hackish and brittle but I couldn't work out another way
            year, month, day = value.split("-")
            # have to int month and day in case zero-padded
            tasks = tasks.filter(modified__year=int(year), modified__month=int(month), modified__day=int(day))
        except:
            tasks = Task.objects.none() # @@@ or throw 404?
    elif field == "state":
        task_filter = None # prevent task filtering
        try:
            state = workflow.REVERSE_STATE_CHOICES[value]
        except KeyError:
            raise Http404
        tasks = tasks.filter(state=state)
    elif field == "assignee":
        if value == "unassigned": # @@@ this means can"t have a username "unassigned":
            tasks = tasks.filter(assignee__isnull=True)
        else:
            try:
                assignee = User.objects.get(username=value)
                tasks = tasks.filter(assignee=assignee)
            except User.DoesNotExist:
                tasks = Task.objects.none() # @@@ or throw 404?
    elif field == "tag":
        tags_list = urllib.unquote_plus(value).split()
        
        task_tags = TaggedItem.tags_for(Task)
        for tag in tags_list:
            if tag.endswith(":*"):
                expanded_tags_list.extend(t.name for t in task_tags.filter(name__startswith=tag[:-1]))
            else:
                expanded_tags_list.append(tag)
        
        tasks = tasks.filter(tags__name__in=expanded_tags_list)
    
    if task_filter is not None:
        # Django will not merge queries that are both not distinct or distinct
        tasks = tasks.distinct() & task_filter.qs
    
    group_by_querydict = request.GET.copy()
    group_by_querydict.pop("group_by", None)
    group_by_querystring = group_by_querydict.urlencode()
    
    ctx = group_context(group, bridge)
    ctx.update({
        "task_filter": task_filter,
        "tasks": tasks,
        "field": field,
        "value": value,
        "group_by": group_by,
        "gbqs": group_by_querystring,
        "is_member": is_member,
        "task_tags": Task.tags.all(),
        "filter_only": filter_only,
        "tags_list": expanded_tags_list,
    })
    
    return render_to_response(template_name, RequestContext(request, ctx))
Example #48
0
    def get_context_data(self, **kwargs):
        context = super(BlogBaseView, self).get_context_data(**kwargs)
        context['blog_tags'] = TaggedItem.tags_for(Blog).order_by('name')
        context['recent_blog_list'] = Blog.objects.recent_posts()

        return context
Example #49
0
    def extract_document(cls, obj_id, obj=None):
        """Extracts indexable attributes from a Question and its answers."""
        fields = ['id', 'title', 'content', 'num_answers', 'solution_id',
                  'is_locked', 'created', 'updated', 'num_votes_past_week',
                  'locale']
        composed_fields = ['creator__username']
        all_fields = fields + composed_fields

        if obj is None:
            # Note: Need to keep this in sync with
            # tasks.update_question_vote_chunk.
            obj = cls.uncached.values(*all_fields).get(pk=obj_id)
        else:
            fixed_obj = dict([(field, getattr(obj, field))
                              for field in fields])
            fixed_obj['creator__username'] = obj.creator.username
            obj = fixed_obj

        d = {}
        d['id'] = obj['id']
        d['document_id'] = cls.get_document_id(obj['id'])
        d['model'] = cls.get_model_name()

        # We do this because get_absolute_url is an instance method
        # and we don't want to create an instance because it's a DB
        # hit and expensive. So we do it by hand. get_absolute_url
        # doesn't change much, so this is probably ok.
        d['url'] = reverse('questions.answers',
                           kwargs={'question_id': obj['id']})

        d['indexed_on'] = int(time.time())

        # TODO: Sphinx stores created and updated as seconds since the
        # epoch, so we convert them to that format here so that the
        # search view works correctly. When we ditch Sphinx, we should
        # see if it's faster to filter on ints or whether we should
        # switch them to dates.
        d['created'] = int(time.mktime(obj['created'].timetuple()))
        d['updated'] = int(time.mktime(obj['updated'].timetuple()))

        topics = Topic.uncached.filter(question__id=obj['id'])
        products = Product.uncached.filter(question__id=obj['id'])
        d['topic'] = [t.slug for t in topics]
        d['product'] = [p.slug for p in products]

        d['question_title'] = obj['title']
        d['question_content'] = obj['content']
        d['question_num_answers'] = obj['num_answers']
        d['question_is_solved'] = bool(obj['solution_id'])
        d['question_is_locked'] = obj['is_locked']
        d['question_has_answers'] = bool(obj['num_answers'])

        d['question_creator'] = obj['creator__username']
        d['question_num_votes'] = (QuestionVote.objects
                          .filter(question=obj['id'])
                          .count())
        d['question_num_votes_past_week'] = obj['num_votes_past_week']

        d['question_tag'] = list(TaggedItem.tags_for(
            Question, Question(pk=obj_id)).values_list('name', flat=True))

        d['question_locale'] = obj['locale']

        answer_values = list(Answer.objects
                                   .filter(question=obj_id)
                                   .values_list('content',
                                                'creator__username'))

        d['question_answer_content'] = [a[0] for a in answer_values]
        d['question_answer_creator'] = list(set(a[1] for a in answer_values))

        if not answer_values:
            d['question_has_helpful'] = False
        else:
            d['question_has_helpful'] = Answer.objects.filter(
                question=obj_id).filter(votes__helpful=True).exists()

        return d
Example #50
0
 def entry_tags(self):
     """Returns a :class:`QuerySet` of :class:`.Tag`\ s that are used on any entries in this blog."""
     entry_pks = list(self.entries.values_list('pk', flat=True))
     kwargs = {'%s__object_id__in' % TaggedItem.tag_relname(): entry_pks}
     return TaggedItem.tags_for(BlogEntry).filter(**kwargs)
Example #51
0
    def extract_document(cls, obj_id, obj=None):
        """Extracts indexable attributes from a Question and its answers."""
        fields = [
            "id",
            "title",
            "content",
            "num_answers",
            "solution_id",
            "is_locked",
            "created",
            "updated",
            "num_votes_past_week",
            "locale",
        ]
        composed_fields = ["creator__username"]
        all_fields = fields + composed_fields

        if obj is None:
            # Note: Need to keep this in sync with
            # tasks.update_question_vote_chunk.
            model = cls.get_model()
            obj = model.uncached.values(*all_fields).get(pk=obj_id)
        else:
            fixed_obj = dict([(field, getattr(obj, field)) for field in fields])
            fixed_obj["creator__username"] = obj.creator.username
            obj = fixed_obj

        d = {}
        d["id"] = obj["id"]
        d["model"] = cls.get_mapping_type_name()

        # We do this because get_absolute_url is an instance method
        # and we don't want to create an instance because it's a DB
        # hit and expensive. So we do it by hand. get_absolute_url
        # doesn't change much, so this is probably ok.
        d["url"] = reverse("questions.answers", kwargs={"question_id": obj["id"]})

        d["indexed_on"] = int(time.time())

        d["created"] = int(time.mktime(obj["created"].timetuple()))
        d["updated"] = int(time.mktime(obj["updated"].timetuple()))

        topics = Topic.uncached.filter(question__id=obj["id"])
        products = Product.uncached.filter(question__id=obj["id"])
        d["topic"] = [t.slug for t in topics]
        d["product"] = [p.slug for p in products]

        d["question_title"] = obj["title"]
        d["question_content"] = obj["content"]
        d["question_num_answers"] = obj["num_answers"]
        d["question_is_solved"] = bool(obj["solution_id"])
        d["question_is_locked"] = obj["is_locked"]
        d["question_has_answers"] = bool(obj["num_answers"])

        d["question_creator"] = obj["creator__username"]
        d["question_num_votes"] = QuestionVote.objects.filter(question=obj["id"]).count()
        d["question_num_votes_past_week"] = obj["num_votes_past_week"]

        d["question_tag"] = list(TaggedItem.tags_for(Question, Question(pk=obj_id)).values_list("name", flat=True))

        d["question_locale"] = obj["locale"]

        answer_values = list(Answer.objects.filter(question=obj_id).values_list("content", "creator__username"))

        d["question_answer_content"] = [a[0] for a in answer_values]
        d["question_answer_creator"] = list(set(a[1] for a in answer_values))

        if not answer_values:
            d["question_has_helpful"] = False
        else:
            d["question_has_helpful"] = Answer.objects.filter(question=obj_id).filter(votes__helpful=True).exists()

        return d