python / expert
Snippet
Django Benutzerdefinierte Template-Filter mit Registrierung
Django Template-Filter transformieren Variablenausgabe in Templates, während benutzerdefinierte Tags komplexe Template-Logik ermöglichen. Dieses Beispiel zeigt mehrere Filtertypen: String-Manipulationsfilter (truncate, highlight), Formatierungsfilter (percentage, phone) und Inclusion-Tags für wiederverwendbare Template-Komponenten. Die Registrierungs-Dekorator-Muster demonstrieren sowohl @register.filter für einfache Transformationen als auch @register.inclusion_tag für Template-Rendering mit Kontextdaten.
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
Erklärung
1
register = template.Library()
Erstelle Template-Bibliothek Instanz zum Registrieren von Filtern/Tags
2
@register.filter(name='truncate_words_html')
Registriere Filter mit benutzerdefiniertem Namen für Template-Nutzung
3
def truncate_words_html(value, arg):
Filter-Funktion erhält Wert und optionales Argument
4
return mark_safe(truncated_text)
Markiere HTML als sicher um Auto-Escaping zu verhindern
5
@register.filter def highlight_search(text, search_term):
Hebe Suchtreffer mit Regex-Substitution hervor
6
pattern = re.compile(re.escape(search_term), re.IGNORECASE)
Baue sicheres Regex-Muster ohne Special-Char-Injection
7
@register.inclusion_tag('tags/breadcrumb.html')
Registriere Template-Tag das eingeschlossenes Template rendert
8
@register.simple_tag def get_menu_items(menu_name, user=None):
Simple Tag für komplexe Datenabfrage mit Caching