【问题标题】:Exclude some Posts from count of tags从标签计数中排除一些帖子
【发布时间】:2018-02-01 21:41:29
【问题描述】:

我正在使用django-taggit 来管理我的标签。 我想包含一个已使用标签的列表,并说明每个标签已使用了多少次。为此,我使用taggit_templatetags2,但我可以避免。

我的models.py

from taggit.managers import TaggableManager

class Post(models.Model):
    ...
    tags = TaggableManager(blank=True)

我的template.html

{% load taggit_templatetags2_tags %}

  {% get_taglist as tags for 'blog.post' %}

  {% for tag in tags %}
    {% if tag.slug != 'draft' and tag.slug != 'retired' %}
      <h4 style="text-align:center"><a href="{% url 'blog:post_list_by_tag' tag.slug %}">
        {{ tag }} ({{ tag.num_times }}) </a></h4>
    {% endif %}
  {% endfor %}

但我想从计数中排除草稿帖子和已退休帖子的所有标签。我不想仅仅排除标签“草稿”和“退休”(我已经这样做了),甚至包括此类帖子可能具有的其他标签。我该怎么做?

例如,我有两个帖子。第一个只有标签“狗”。第二个有标签“狗”和“草稿”。这是一个草稿,尚未发布的帖子。

我的代码会给出:dog (2),因为它会计算所有帖子的标签。当用户点击“狗”时,它会出现一个页面,其中包含所有已发布的带有狗标签的帖子,所以在我们的例子中,一个帖子是因为第二个帖子没有发布。用户会问自己:有两个狗帖,第二个在哪里?这不好。我也不想暗示即将发布的帖子的论点。

可能我必须弄乱taggit_templatetags2 代码...

老实说这段代码对我来说很难理解,而且我认为最好不要直接更改原始代码,否则在第一次更新时我的代码会丢失。

这里是taggit_templatetags2的一些代码:

@register.tag
class GetTagList(TaggitBaseTag):
    name = 'get_taglist'

    def get_value(self, context, varname, forvar, limit=settings.LIMIT, order_by=settings.TAG_LIST_ORDER_BY):
        # TODO: remove default value for limit, report a bug in the application
        # django-classy-tags, the default value does not work
        queryset = get_queryset(
            forvar,
            settings.TAGGED_ITEM_MODEL,
            settings.TAG_MODEL)
        queryset = queryset.order_by(order_by)
        context[varname] = queryset
        if limit:
            queryset = queryset[:limit]
        return ''

def get_queryset(forvar, taggeditem_model, tag_model):
    through_opts = taggeditem_model._meta
    count_field = (
        "%s_%s_items" % (
            through_opts.app_label,
            through_opts.object_name)).lower()

    if forvar is None:
        # get all tags
        queryset = tag_model.objects.all()
    else:
        # extract app label and model name
        beginning, applabel, model = None, None, None
        try:
            beginning, applabel, model = forvar.rsplit('.', 2)
        except ValueError:
            try:
                applabel, model = forvar.rsplit('.', 1)
            except ValueError:
                applabel = forvar
        applabel = applabel.lower()

        # filter tagged items
        if model is None:
            # Get tags for a whole app
            queryset = taggeditem_model.objects.filter(
                content_type__app_label=applabel)
            tag_ids = queryset.values_list('tag_id', flat=True)
            queryset = tag_model.objects.filter(id__in=tag_ids)
        else:
            # Get tags for a model
            model = model.lower()
            if ":" in model:
                model, manager_attr = model.split(":", 1)
            else:
                manager_attr = "tags"
            model_class = get_model(applabel, model)
            if not model_class:
                raise Exception(
                    'Not found such a model "%s" in the application "%s"' %
                    (model, applabel))
            manager = getattr(model_class, manager_attr)
            queryset = manager.all()
            through_opts = manager.through._meta
            count_field = ("%s_%s_items" % (through_opts.app_label,
                                            through_opts.object_name)).lower()

    if count_field is None:
        # Retain compatibility with older versions of Django taggit
        # a version check (for example taggit.VERSION <= (0,8,0)) does NOT
        # work because of the version (0,8,0) of the current dev version of
        # django-taggit
        try:
            return queryset.annotate(
                num_times=Count(settings.TAG_FIELD_RELATED_NAME))
        except FieldError:
            return queryset.annotate(
                num_times=Count('taggit_taggeditem_items'))
    else:
        return queryset.annotate(num_times=Count(count_field))

地点:

queryset = manager.all() 给出了所有标签的列表

count_field 是一个字符串:taggit_taggeditem_items

queryset.annotate(num_times=Count(count_field)) 是带有额外字段num_times 的查询集,

【问题讨论】:

    标签: django django-taggit django-aggregation


    【解决方案1】:
    • 如果您想有效地从查询集中排除项目,请尝试在您的查询集中使用 exclude 方法:

      queryset.exclude(slug__in=['draft', 'retired'])

    • 您也可以尝试使用 values 方法来计算您的标签的出现次数。如果我理解正确,请尝试:

      queryset.values('id').annotate(num_times=Count(count_field))

    【讨论】:

    • 感谢您的帮助,但恐怕您的代码现在无法帮助我。我正在使用两个外部应用程序(taggit 和 taggit_templatetag),所以我不知道在哪里可以找到查询集或如何拦截它们。同样从标签查询集中有效地排除这些标签很有用,但我的首要任务是从用于计算标签的帖子查询集中排除带有这些标签的帖子......如果我能做到这一点,我不需要计算自己的标签, taggit_templatetag 会为我做的。但是,如果我决定不使用此应用程序,您的代码将很有用。我编辑了我的帖子以添加一个示例
    【解决方案2】:

    所以,我在这里所做的,没有 taggit_template_tags2,可能可以优化,不客气!

    我的model.py

    class Post(models.Model):
        ...
        tags = TaggableManager(blank=True)
    

    我的views.py

    ...
    #filter the posts that I want to count
    tag_selected = get_object_or_404(Tag, slug='ritired')
    posts = Post.objects.filter(published_date__lte=timezone.now()).exclude(tags__in=[tag_selected])
    #create a dict with all the tags and value=0
    tag_dict = {}
    tags=Post.tags.all()
    for tag in tags:
        tag_dict[tag]=0
    #count the tags in the post and update the dict
    for post in posts:
        post_tag=post.tags.all()
        for tag in post_tag:
            tag_dict[tag]+=1
    #delete the key with value=0
    tag_dict = {key: value for key, value in tag_dict.items() if value != 0}
    #pass the dict to the template
    context_dict={}
    context_dict['tag_dict']=tag_dict
    return render(request, 'blog/post_list.html', context_dict)
    

    我的template.html

      {% for key, value in tag_dict.items %}
        <h4 style="text-align:center"><a href="{% url 'blog:post_list_by_tag' key.slug %}">
          {{ key }} ({{ value }})
        </h4>
      {% endfor %}
    

    快速简单!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-04
      • 2014-01-14
      • 1970-01-01
      • 2011-01-25
      • 2019-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多