从标签计数中排除一些帖子
Exclude some Posts from count of tags
我正在使用 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 %}
但我想从计数中排除草稿 posts 和退休的 posts 的所有标签。我不想只排除 'draft' 和 'retired' 标签(我已经在这样做了),甚至还想排除 post 可能具有的其他标签。我该怎么做?
例如我有两个post。第一个只有标签 'dog'。第二个有标签 'dog' 和 'draft'。这是草稿,post 尚未发布。
我的代码会给出:dog (2) 因为它计算了所有 post 的标签。当用户单击 'dog' 时,将出现一个页面,其中包含所有已发布的 post 和狗标签,因此在我们的例子中是一个 post,因为第二个未发布。用户会问自己:有两条狗post,第二条在哪里?这不好。另外,我不想暗示即将出版的 posts.
的论点
可能我必须弄乱 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
、
的查询集
如果您想有效地从查询集中排除项目,请尝试在您的查询集中使用 exclude 方法:
queryset.exclude(slug__in=['draft', 'retired'])
您也可以尝试使用values方法来计算您的标签出现的次数。如果我理解正确的话,试试:
queryset.values('id').注释(num_times=计数(count_field))
所以,我所做的,没有 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 %}
快速简单!
我正在使用 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 %}
但我想从计数中排除草稿 posts 和退休的 posts 的所有标签。我不想只排除 'draft' 和 'retired' 标签(我已经在这样做了),甚至还想排除 post 可能具有的其他标签。我该怎么做?
例如我有两个post。第一个只有标签 'dog'。第二个有标签 'dog' 和 'draft'。这是草稿,post 尚未发布。
我的代码会给出:dog (2) 因为它计算了所有 post 的标签。当用户单击 'dog' 时,将出现一个页面,其中包含所有已发布的 post 和狗标签,因此在我们的例子中是一个 post,因为第二个未发布。用户会问自己:有两条狗post,第二条在哪里?这不好。另外,我不想暗示即将出版的 posts.
的论点可能我必须弄乱 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
、
如果您想有效地从查询集中排除项目,请尝试在您的查询集中使用 exclude 方法:
queryset.exclude(slug__in=['draft', 'retired'])
您也可以尝试使用values方法来计算您的标签出现的次数。如果我理解正确的话,试试:
queryset.values('id').注释(num_times=计数(count_field))
所以,我所做的,没有 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 %}
快速简单!