from django import template
from django.db.models import Count
from blog.models import Post, Tag
register = template.Library()
@register.simple_tag
def total_posts():
"""Return total published posts count."""
return Post.objects.filter(status='published').count()
@register.inclusion_tag('blog/partials/latest_posts.html')
def show_latest_posts(count=5):
"""Render latest published posts."""
posts = Post.objects.filter(
status='published'
).select_related('author').order_by('-published_at')[:count]
return {'posts': posts}
@register.simple_tag
def get_popular_tags(limit=10):
"""Get most used tags."""
return Tag.objects.annotate(
post_count=Count('posts')
).order_by('-post_count')[:limit]
<div class="latest-posts">
<h3>Latest Posts</h3>
<ul>
{% for post in posts %}
<li>
<a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
<span class="author">by {{ post.author }}</span>
</li>
{% empty %}
<li>No posts yet.</li>
{% endfor %}
</ul>
</div>
Template tags extend Django's template language. I create simple tags with @register.simple_tag and inclusion tags with @register.inclusion_tag for rendering template snippets with context. Assignment tags store results in template variables. I place tags in templatetags/ directory and load them with {% load my_tags %}. For complex logic, I write a full tag class inheriting from template.Node. Template tags should be stateless and focused on presentation, not business logic. This keeps templates DRY and promotes reusability across the site.