Exclude some posts from tags

I am using django-taggit to manage my tag. I want to include a list of tags used, indicating how many times each has been used. I use taggit_templatetags2 for this, but I can avoid.

My models.py :

 from taggit.managers import TaggableManager class Post(models.Model): ... tags = TaggableManager(blank=True) 

My 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 %} 

But I want to exclude from the count all tags of draft messages and retired posts. I don’t want to just exclude the “draft” tags and “resignation” (I already do this), but even other tags that may have such messages. How can i do this?

For example, I have two posts. The first has only a dog tag. The second has the tags “dog” and “draft”. This is a draft, the message has not yet been published.

My code will give: dog (2) because it counts the tags of all messages. When the user clicks on the "dog", a page with the entire published message with the dog tag will appear, therefore, in our case, one message, because the second is not published. The user will ask himself: there are two dogs, where is the second? This is bad. In addition, I do not want to hint at the argument of soon published posts.

Maybe I need to mess with the code taggit_templatetags2 ...

Honestly, it’s hard for me to understand this code, I also think that it would be better not to change the source code directly, or my code will be lost on the first update.

Here is the code 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)) 

Where:

queryset = manager.all() contains a list of all tags

count_field - string: taggit_taggeditem_items

queryset.annotate(num_times=Count(count_field)) is a request with an additional field num_times ,

0
source share
2 answers

So here is what I did, without taggit_template_tags2, you can probably drop it, please!

My model.py :

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

My 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) 

My 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 %} 

Fast and easy!

0
source
  • if you want to effectively exclude elements from the query set, try using the exclude method in your query:

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

  • You can also use the values method to calculate the number of occurrences of your tag. if I understand correctly, try:

    queryset.values ​​('ID'). Annotations (num_times = Count (count_field))

0
source

Source: https://habr.com/ru/post/1274607/


All Articles