Django嵌入式自定义模板标签

u0sqgete  于 2023-10-21  发布在  Go
关注(0)|答案(1)|浏览(147)

我正在尝试为Django创建一个自定义模板标签。但是,它没有产生任何产出;也不从解析器接收任何信息。
下面是templatetag本身的代码:

class MediaQueryNode(Node):
            def __init__(self, xsmall, small, medium, large, xlarge, wrap=None):
                self.xsmall = xsmall
                self.small = small
                self.medium = medium
                self.large = large
                self.xlarge = xlarge
                self.wrap = wrap
            
            def render(self, context):
                xsmall = None
                small  = None
                medium = None
                large  = None
                xlarge = None
            
                context = context.flatten()
            
                if self.xsmall:
                    xsmall = self.xsmall.render(context)
            
                if self.small:
                    small = self.small.render(context)
            
                if self.medium:
                    medium = self.medium.render(context)
            
                if self.large:
                    large = self.large.render(context)
            
                if self.xlarge:
                    xlarge = self.xlarge.render(context)
                
                template = loader.get_template("templatetags/mediaquery.html")
            
                context.update({
                
                    "mediaquery_xsmall": xsmall,
                    "mediaquery_small": small,
                    "mediaquery_medium": medium,
                    "mediaquery_large": large,
                    "mediaquery_xlarge": xlarge,
                
                    "wrap": self.wrap.resolve(context) if self.wrap else False,
                
                })
            
                return template.render(context)
            
        @register.tag("mediaquery")
        def do_media_query(parser, token):
            
            subtags = ["xsmall", "small", "medium", "large", "xlarge"]
            tag_content = {tag: None for tag in subtags}
            processed_tags = []
            
            end_tag = 'endmediaquery'
            
            # Skip any content between {% mediaquery %} and the first subtag
            parser.parse(subtags + [end_tag])
            
            while parser.tokens:
                token = parser.next_token()
            
                if token.token_type == TokenType.BLOCK:
                    token_name = token.contents
            
                    if token_name in processed_tags:
                        raise TemplateSyntaxError(f"Duplicate {token_name} tag")
                    
                    if token_name not in subtags and token_name != end_tag:
                        raise TemplateSyntaxError(f"Unknown tag {token_name}")
                    
                    if token_name == end_tag:
                        break
                    
                    processed_tags.append(token_name)
                    parser.delete_first_token()
            
                    # Here, instead of just saving the token, we parse until the next known token to get the content block.
                    tag_content[token_name] = parser.parse(subtags + [end_tag])
            
            print(tag_content)
            
            return MediaQueryNode(
                xsmall=tag_content['xsmall'], 
                small=tag_content['small'], 
                medium=tag_content['medium'], 
                large=tag_content['large'], 
                xlarge=tag_content['xlarge']
            )

当I print(tag_content)时,它在终端中显示以下输出:

{'xsmall': [], 'small': [], 'medium': [], 'large': [], 'xlarge': []}

如图所示,它提供的输出是空的。
模板标签是这样使用的;并且块的顺序不应该是重要的。即:从xlarge开始,然后使用较小的比例应该是安全的,反之亦然或混乱。我还希望能够省去标签(这是所有可能的,但如前所述,显示为空)。
它应该始终使用{% xsmall %}{% medium %}等声明之后的文本/代码。

{% mediaquery %}
                ... content (this can safely be discarded and should serve no use) ...
            {% small %}
                ... sm content ...
            {% xsmall %}
                ... xs content ...
            {% medium %}
                ... md content ...
            {% large %}
                ... lg content ...
            {% xlarge %}
                ... xl content ...
        {% endmediaquery %}

然后标签应该在模板中呈现为:

{% if wrap %}<style>{%endif%}
  {% if mediaquery_xsmall %}
    @media (min-width: 576px) {
      {{mediaquery_xsmall}}
    }
  {% endif %}
  {% if mediaquery_small %}
    @media (min-width: 768px) {
      {{mediaquery_small}}
    }
  {% endif %}
  {% if mediaquery_medium %}
    @media (min-width: 992px) {
      {{mediaquery_medium}}
    }
  {% endif %}
  {% if mediaquery_large %}
    @media (min-width: 1200px) {
      {{mediaquery_large}}
    }
  {% endif %}
  {% if mediaquery_xlarge %}
    @media (min-width: 1400px) {
      {{mediaquery_xlarge}}
    }
  {% endif %}
{% if wrap %}</style>{%endif%}
sirbozc5

sirbozc51#

通过删除for循环中的parser.delete_first_token()行修复了它。工作代码:

class MediaQueryNode(Node):
    def __init__(self, base: Node, xsmall: Node, small: Node, medium: Node, large: Node, xlarge: Node, wrap: Node=None):
        self.base   = base
        self.xsmall = xsmall
        self.small  = small
        self.medium = medium
        self.large  = large
        self.xlarge = xlarge
        self.wrap   = wrap

    def render(self, context):
        base   = None
        xsmall = None
        small  = None
        medium = None
        large  = None
        xlarge = None

        context = context.flatten()

        if self.base:
            base = self.base.render(context)
        if self.xsmall:
            xsmall = self.xsmall.render(context)
        if self.small:
            small = self.small.render(context)
        if self.medium:
            medium = self.medium.render(context)
        if self.large:
            large = self.large.render(context)
        if self.xlarge:
            xlarge = self.xlarge.render(context)
        
        template: Template = loader.get_template("templatetags/mediaquery.html")

        context.update({
            "mediaquery_base": base,
            "mediaquery_xsmall": xsmall,
            "mediaquery_small": small,
            "mediaquery_medium": medium,
            "mediaquery_large": large,
            "mediaquery_xlarge": xlarge,
            "mediaquery_wrap": self.wrap.resolve(context) if self.wrap else False,
        })

        return template.render(context)

@register.tag("mediaquery")
def do_media_query(parser: Parser, token):

    subtags = ["xsmall", "small", "medium", "large", "xlarge"]
    tag_content = {tag: None for tag in subtags}
    processed_tags = []

    end_tag = 'endmediaquery'

    # Skip any content between {% mediaquery %} and the first subtag
    base = parser.parse(subtags + [end_tag])
    token = parser.next_token()

    while parser.tokens:

        if token.token_type == TokenType.BLOCK:
            token_name = token.contents

            if token_name in processed_tags:
                raise TemplateSyntaxError(f"Duplicate {token_name} tag")
            
            if token_name not in subtags and token_name != end_tag:
                raise TemplateSyntaxError(f"Unknown tag {token_name}")
            
            if token_name == end_tag:
                break
            
            processed_tags.append(token_name)

            subtags.remove(token_name)

            # Here, instead of just saving the token, we parse until the next known token to get the content block.
            tag_content[token_name] = parser.parse(subtags + [end_tag])

        token = parser.next_token()

    return MediaQueryNode(
        base=base,
        xsmall=tag_content['xsmall'], 
        small=tag_content['small'], 
        medium=tag_content['medium'], 
        large=tag_content['large'], 
        xlarge=tag_content['xlarge']
    )

相关问题