python / expert
Snippet
Django Custom Template Filters with Registration
Django template filters transform variable output in templates, while custom tags enable complex template logic. This example showcases multiple filter types: string manipulation filters (truncate, highlight), formatting filters (percentage, phone), and inclusion tags for reusable template components. The registration decorator patterns demonstrate both @register.filter for simple transformations and @register.inclusion_tag for template rendering with context data.
snippet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import refrom django import templatefrom django.utils.safestring import mark_safefrom django.utils.html import strip_tagsregister = template.Library()@register.filter(name='truncate_words_html')def truncate_words_html(value, arg):"""Truncate HTML string to given word count without breaking tags."""from bs4 import BeautifulSoupsoup = BeautifulSoup(value, 'html.parser')text = soup.get_text()words = text.split()if len(words) <= arg:return valuetruncated_text = ' '.join(words[:arg]) + '...'return mark_safe(truncated_text)@register.filterdef highlight_search(text, search_term):"""Highlight search term in text with HTML markup."""if not search_term:return textpattern = re.compile(re.escape(search_term), re.IGNORECASE)highlighted = pattern.sub(lambda m: f'<mark>{m.group()}</mark>', text)return mark_safe(highlighted)@register.filterdef percentage(value, decimals=0):"""Format number as percentage string."""try:return f'{float(value) * 100:.{decimals}f}%'except (ValueError, TypeError):return '0%'@register.filterdef phone_format(value):"""Format phone number with country code grouping."""digits = re.sub(r'\D', '', value)if len(digits) == 10:return f'({digits[:3]}) {digits[3:6]}-{digits[6:]}'elif len(digits) == 11 and digits[0] == '1':return f'+1 ({digits[1:4]}) {digits[4:7]}-{digits[7:]}'return value@register.inclusion_tag('tags/breadcrumb.html')def render_breadcrumb(items):"""Render navigation breadcrumb from list of (url, label) tuples."""return {'items': items}@register.simple_tagdef get_menu_items(menu_name, user=None):"""Retrieve and cache menu items from database."""from django.core.cache import cachefrom .models import MenuItemcache_key = f'menu_{menu_name}'items = cache.get(cache_key)if items is None:queryset = MenuItem.objects.filter(menu_name=menu_name, is_active=True)if user and not user.is_superuser:queryset = queryset.filter(requires_auth=False)items = list(queryset.select_related('parent').order_by('sort_order'))cache.set(cache_key, items, 3600)return items
django
Breakdown
1
register = template.Library()
Create template library instance for registering filters/tags
2
@register.filter(name='truncate_words_html')
Register filter with custom name for template usage
3
def truncate_words_html(value, arg):
Filter function receives value and optional argument
4
return mark_safe(truncated_text)
Mark HTML as safe to prevent auto-escaping
5
@register.filter def highlight_search(text, search_term):
Highlight search matches using regex substitution
6
pattern = re.compile(re.escape(search_term), re.IGNORECASE)
Build safe regex pattern avoiding special char injection
7
@register.inclusion_tag('tags/breadcrumb.html')
Register template tag that renders included template
8
@register.simple_tag def get_menu_items(menu_name, user=None):
Simple tag for complex data retrieval with caching