CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-django-taggit

A reusable Django application for simple tagging with comprehensive manager and form support.

Pending
Overview
Eval results
Files

view-helpers.mddocs/

View Helpers

Generic view components for creating tag-filtered list views and displaying objects by tag. Django-taggit provides utilities for implementing tag-based filtering in both function-based and class-based views.

Capabilities

Function-Based View Helper

Generic view function for listing objects filtered by a specific tag.

def tagged_object_list(request, slug, queryset, **kwargs):
    """
    Generic view function for listing objects with specific tag.
    
    Parameters:
    - request: HTTP request object
    - slug (str): Tag slug to filter by
    - queryset: Model queryset to filter
    - **kwargs: Additional view parameters passed to generic view
    
    Returns:
    HttpResponse: Rendered template with filtered object list
    
    Raises:
    Http404: If tag with given slug does not exist
    """
from django.shortcuts import render
from taggit.views import tagged_object_list
from myapp.models import Article

def articles_by_tag(request, slug):
    return tagged_object_list(
        request, 
        slug, 
        Article.objects.all(),
        template_name='articles/tagged_list.html',
        context_object_name='articles'
    )

Class-Based View Mixin

Mixin for class-based views that adds tag-based filtering functionality.

class TagListMixin:
    """
    Mixin for views filtering objects by tag.
    
    Provides tag-based filtering functionality for class-based views,
    particularly ListView, with automatic template name resolution
    and context enhancement.
    """
    tag_suffix = "_tag"
    
    def dispatch(self, request, *args, **kwargs):
        """
        Handle request dispatch with tag filtering setup.
        
        Parameters:
        - request: HTTP request object
        - *args: Positional arguments
        - **kwargs: Keyword arguments including 'slug' for tag
        
        Returns:
        HttpResponse: Response from parent dispatch method
        
        Raises:
        Http404: If tag with given slug does not exist
        """
    
    def get_queryset(self, **kwargs):
        """
        Return queryset filtered by tag.
        
        Parameters:
        - **kwargs: Additional filtering parameters
        
        Returns:
        QuerySet: Filtered queryset containing only objects with the tag
        """
    
    def get_template_names(self):
        """
        Return template names with tag-specific variants.
        
        Adds template names with tag suffix to support
        tag-specific templates while maintaining fallbacks.
        
        Returns:
        list: List of template names to try
        """
    
    def get_context_data(self, **kwargs):
        """
        Add tag context to template.
        
        Parameters:
        - **kwargs: Existing context data
        
        Returns:
        dict: Context dictionary with added 'tag' variable
        """

Usage Examples

Basic Function-Based View

Simple implementation using the tagged_object_list function.

from django.urls import path
from taggit.views import tagged_object_list
from myapp.models import BlogPost

# In urls.py
urlpatterns = [
    path('posts/tag/<slug:slug>/', 
         lambda request, slug: tagged_object_list(
             request, slug, BlogPost.objects.published()
         ), 
         name='posts_by_tag'),
]

# Template: myapp/blogpost_list.html
# Context variables: object_list, tag

Class-Based View with TagListMixin

Using the mixin with ListView for enhanced functionality.

from django.views.generic import ListView
from taggit.views import TagListMixin
from myapp.models import Article

class ArticleTagListView(TagListMixin, ListView):
    model = Article
    context_object_name = 'articles'
    paginate_by = 10
    
    def get_queryset(self):
        # Call parent to get tag-filtered queryset
        queryset = super().get_queryset()
        # Add additional filtering
        return queryset.filter(published=True).order_by('-created_at')

# In urls.py
path('articles/tag/<slug:slug>/', ArticleTagListView.as_view(), name='articles_by_tag')

Advanced Tag View Implementation

Custom view with additional features and error handling.

from django.views.generic import ListView
from django.shortcuts import get_object_or_404
from django.db.models import Count
from taggit.models import Tag
from myapp.models import Article

class AdvancedTagView(ListView):
    model = Article
    template_name = 'articles/tag_detail.html'
    context_object_name = 'articles'
    paginate_by = 20
    
    def dispatch(self, request, *args, **kwargs):
        self.tag = get_object_or_404(Tag, slug=kwargs['slug'])
        return super().dispatch(request, *args, **kwargs)
    
    def get_queryset(self):
        return Article.objects.filter(
            tags=self.tag,
            published=True
        ).select_related('author').order_by('-created_at')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update({
            'tag': self.tag,
            'article_count': self.get_queryset().count(),
            'related_tags': Tag.objects.filter(
                article__in=self.get_queryset()
            ).exclude(id=self.tag.id).annotate(
                usage_count=Count('article')
            ).order_by('-usage_count')[:10]
        })
        return context

Multiple Tag Filtering

View that filters by multiple tags simultaneously.

from django.views.generic import ListView
from django.db.models import Q
from taggit.models import Tag

class MultipleTagView(ListView):
    model = Article
    template_name = 'articles/multi_tag.html'
    
    def get_queryset(self):
        tag_slugs = self.request.GET.get('tags', '').split(',')
        tag_slugs = [slug.strip() for slug in tag_slugs if slug.strip()]
        
        if not tag_slugs:
            return Article.objects.none()
        
        # Get all specified tags
        tags = Tag.objects.filter(slug__in=tag_slugs)
        
        # Filter articles that have ALL specified tags
        queryset = Article.objects.published()
        for tag in tags:
            queryset = queryset.filter(tags=tag)
        
        return queryset.distinct()
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        tag_slugs = self.request.GET.get('tags', '').split(',')
        context['active_tags'] = Tag.objects.filter(
            slug__in=[s.strip() for s in tag_slugs if s.strip()]
        )
        return context

# Usage: /articles/multi-tag/?tags=python,django,tutorial

Tag Cloud View

View for displaying a tag cloud with usage counts.

from django.views.generic import TemplateView
from django.db.models import Count
from taggit.models import Tag

class TagCloudView(TemplateView):
    template_name = 'tags/cloud.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # Get tags with usage counts
        tags_with_counts = Tag.objects.annotate(
            usage_count=Count('tagged_items')
        ).filter(usage_count__gt=0).order_by('name')
        
        # Calculate relative sizes for cloud display
        if tags_with_counts:
            max_count = max(tag.usage_count for tag in tags_with_counts)
            min_count = min(tag.usage_count for tag in tags_with_counts)
            
            for tag in tags_with_counts:
                if max_count == min_count:
                    tag.weight = 1.0
                else:
                    tag.weight = (tag.usage_count - min_count) / (max_count - min_count)
        
        context.update({
            'tags': tags_with_counts,
            'tag_count': tags_with_counts.count()
        })
        return context

API Integration Views

Views for tag-related API endpoints.

from django.http import JsonResponse
from django.views.generic import View
from django.db.models import Count
from taggit.models import Tag

class TagAutocompleteView(View):
    """Autocomplete API for tag suggestions."""
    
    def get(self, request):
        query = request.GET.get('q', '').strip()
        if not query:
            return JsonResponse({'tags': []})
        
        tags = Tag.objects.filter(
            name__icontains=query
        ).annotate(
            usage_count=Count('tagged_items')
        ).order_by('-usage_count', 'name')[:10]
        
        data = {
            'tags': [
                {
                    'name': tag.name,
                    'slug': tag.slug,
                    'usage_count': tag.usage_count
                }
                for tag in tags
            ]
        }
        return JsonResponse(data)

class PopularTagsView(View):
    """API endpoint for most popular tags."""
    
    def get(self, request):
        limit = int(request.GET.get('limit', 20))
        tags = Tag.objects.annotate(
            usage_count=Count('tagged_items')
        ).filter(usage_count__gt=0).order_by('-usage_count')[:limit]
        
        data = {
            'tags': [
                {
                    'name': tag.name,
                    'slug': tag.slug,
                    'usage_count': tag.usage_count
                }
                for tag in tags
            ]
        }
        return JsonResponse(data)

Template Integration

Basic Template Structure

Templates for tag-filtered views with common patterns.

<!-- articles/tagged_list.html -->
<h1>Articles tagged with "{{ tag.name }}"</h1>

<div class="tag-info">
    <p>{{ articles|length }} article{{ articles|length|pluralize }} found</p>
</div>

<div class="articles">
    {% for article in articles %}
        <article class="article-summary">
            <h2><a href="{{ article.get_absolute_url }}">{{ article.title }}</a></h2>
            <p>{{ article.summary }}</p>
            <div class="article-tags">
                {% for article_tag in article.tags.all %}
                    <a href="{% url 'articles_by_tag' article_tag.slug %}" 
                       class="tag {% if article_tag == tag %}current{% endif %}">
                        {{ article_tag.name }}
                    </a>
                {% endfor %}
            </div>
        </article>
    {% empty %}
        <p>No articles found with tag "{{ tag.name }}".</p>
    {% endfor %}
</div>

<!-- Pagination -->
{% if is_paginated %}
    <div class="pagination">
        {% if page_obj.has_previous %}
            <a href="?page={{ page_obj.previous_page_number }}">Previous</a>
        {% endif %}
        
        <span class="page-info">
            Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
        </span>
        
        {% if page_obj.has_next %}
            <a href="?page={{ page_obj.next_page_number }}">Next</a>
        {% endif %}
    </div>
{% endif %}

Tag Cloud Template

Template for displaying tag clouds with weighted sizes.

<!-- tags/cloud.html -->
<div class="tag-cloud">
    <h2>Tag Cloud</h2>
    <div class="cloud-container">
        {% for tag in tags %}
            <a href="{% url 'articles_by_tag' tag.slug %}" 
               class="cloud-tag" 
               style="font-size: {{ tag.weight|floatformat:1|add:'1' }}em;"
               title="{{ tag.usage_count }} article{{ tag.usage_count|pluralize }}">
                {{ tag.name }}
            </a>
        {% endfor %}
    </div>
</div>

<style>
.tag-cloud {
    margin: 2rem 0;
}

.cloud-container {
    line-height: 1.8;
}

.cloud-tag {
    display: inline-block;
    margin: 0.2em 0.4em;
    padding: 0.2em 0.4em;
    background: #f0f0f0;
    border-radius: 3px;
    text-decoration: none;
    color: #333;
    transition: background 0.2s;
}

.cloud-tag:hover {
    background: #e0e0e0;
}
</style>

URL Configuration

URL Patterns

Common URL patterns for tag-based views.

# urls.py
from django.urls import path
from taggit.views import tagged_object_list
from myapp.views import (
    ArticleTagListView, AdvancedTagView, MultipleTagView,
    TagCloudView, TagAutocompleteView, PopularTagsView
)
from myapp.models import Article

app_name = 'tags'

urlpatterns = [
    # Function-based view
    path('articles/<slug:slug>/', 
         lambda request, slug: tagged_object_list(
             request, slug, Article.objects.published()
         ), 
         name='articles_by_tag_simple'),
    
    # Class-based views
    path('articles/tag/<slug:slug>/', 
         ArticleTagListView.as_view(), 
         name='articles_by_tag'),
    
    path('advanced/<slug:slug>/', 
         AdvancedTagView.as_view(), 
         name='advanced_tag_view'),
    
    path('multi-tag/', 
         MultipleTagView.as_view(), 
         name='multi_tag_view'),
    
    # Tag cloud
    path('cloud/', 
         TagCloudView.as_view(), 
         name='tag_cloud'),
    
    # API endpoints
    path('api/autocomplete/', 
         TagAutocompleteView.as_view(), 
         name='tag_autocomplete'),
    
    path('api/popular/', 
         PopularTagsView.as_view(), 
         name='popular_tags'),
]

Install with Tessl CLI

npx tessl i tessl/pypi-django-taggit

docs

admin-interface.md

form-integration.md

index.md

model-integration.md

rest-framework.md

tag-operations.md

utilities-management.md

view-helpers.md

tile.json