Django模板break/continue扩展适配Django2.0+Python3报错求助
Great question! That error pops up because the old Django snippet you’re using relies on template utilities that moved locations or became obsolete in Django 2.0+, paired with Python 3’s Unicode-first string system. Let’s break down the fixes step by step:
What’s Broken?
template.mark_safeno longer exists: Django 2.0 moved themark_safefunction fromdjango.templatetodjango.utils.safestringas part of a cleanup of template-related tools.template.force_unicodeis unnecessary: Python 3 uses Unicode strings by default, so this Python 2-era function (used to convert bytes to Unicode) was completely removed from Django’s API.
Fixed Code Implementation
Here’s the updated version of the snippet that works with Django 2.0+ and Python 3, including the full implementation for {% break %} and {% continue %} tags:
from django import template from django.utils.safestring import mark_safe from django.template.base import Node, NodeList, TemplateSyntaxError register = template.Library() # Break tag logic class BreakNode(Node): def render(self, context): # Set flag to trigger break in custom loop node context['__break__'] = True return '' @register.tag('break') def do_break(parser, token): return BreakNode() # Continue tag logic class ContinueNode(Node): def render(self, context): # Set flag to trigger continue in custom loop node context['__continue__'] = True return '' @register.tag('continue') def do_continue(parser, token): return ContinueNode() # Custom for loop node that supports break/continue class ForLoopNode(Node): def __init__(self, loopvars, sequence, nodelist, nodelist_empty=None): self.loopvars = loopvars self.sequence = sequence self.nodelist = nodelist self.nodelist_empty = nodelist_empty or NodeList() def render(self, context): sequence = self.sequence.resolve(context, True) if not sequence: return self.nodelist_empty.render(context) output = [] for idx, item in enumerate(sequence): # Populate standard forloop context variables context['forloop'] = { 'counter': idx + 1, 'counter0': idx, 'revcounter': len(sequence) - idx, 'revcounter0': len(sequence) - idx - 1, 'first': idx == 0, 'last': idx == len(sequence) - 1, } # Assign loop variables to context if len(self.loopvars) == 1: context[self.loopvars[0]] = item else: # Handle multi-variable loops like {% for key, val in dict.items %} for var, val in zip(self.loopvars, item): context[var] = val # Reset break/continue flags before rendering context.pop('__break__', None) context.pop('__continue__', None) rendered_chunk = self.nodelist.render(context) # Check for break/continue signals if context.get('__break__'): break if context.get('__continue__'): continue output.append(rendered_chunk) # Clean up context to avoid leaking variables for var in self.loopvars: context.pop(var, None) context.pop('forloop', None) # Mark output as safe HTML (matches original snippet's intent) return mark_safe(''.join(output)) # Override default for tag to use our custom loop node @register.tag('for') def do_for(parser, token): bits = token.split_contents() if len(bits) < 4 or bits[2] != 'in': raise TemplateSyntaxError("Invalid for tag syntax") loopvars = bits[1].split(',') loopvars = [var.strip() for var in loopvars] sequence = parser.compile_filter(bits[3]) nodelist = parser.parse(('empty', 'endfor',)) token = parser.next_token() if token.contents == 'empty': nodelist_empty = parser.parse(('endfor',)) parser.delete_first_token() else: nodelist_empty = NodeList() return ForLoopNode(loopvars, sequence, nodelist, nodelist_empty)
Key Changes Explained:
- Replaced
template.mark_safe: We now import it fromdjango.utils.safestring, the correct location in Django 2.0+. - Removed
force_unicode: Python 3 strings are Unicode by default, so we can directly join rendered output without conversion. - Cleaned up context: Ensured loop variables and flags don’t linger in the template context after the loop finishes.
This updated code will work seamlessly in Django 2.0+ and all Python 3 versions, eliminating the AttributeError you encountered.
内容的提问来源于stack exchange,提问作者Rajni Chandra
相关产品推荐
相关产品推荐

