You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django模板渲染问题:Model中带变量的HTML代码无法解析

问题描述

我在数据库中存储了带Django模板变量的HTML代码,但渲染时Django无法识别product.price这类变量,直接把它们当成字符串输出了。

相关代码

Model代码(model.py)

class Badge(models.Model):
    
    name = models.CharField(max_length=255)
    code = models.CharField(max_length=700, default='<h5><span class="badge bg-primary ms-2">New</span></h5>')
    code_price = models.CharField(max_length=700, default='<s>{{product.price | safe}}</s><strong class="ms-2 text-danger">{{product.get_price_with_discount() | safe}}</strong>')
    # product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='badges')
    
    def __str__(self):
        return self.name

class Product(models.Model):
    """产品模型"""

    name = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    image = models.ImageField(upload_to='static/img/' , default='/static/img/404.png')
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    type = models.ForeignKey(Badge, on_delete=models.CASCADE, related_name= "products")
    
    def get_price_with_discount(self):
        discount = (self.price) * (10 / 100)
        return self.price - discount

模板代码(services.html)

<section>
    <div class="text-center container py-5">
        <h4 class="mt-4 mb-5"><strong>畅销品</strong></h4>

        <div class="row">
            {% for product in products %}

            <div class="col-lg-4 col-md-12 mb-4">
                <div class="card">
                    <div class="bg-image hover-zoom ripple ripple-surface ripple-surface-light"
                        data-mdb-ripple-color="light">
                        <img src="{{product.image.url}}" class="w-100" style="height: 500px;" />
                        <a href="#!">
                            <div class="mask">
                                <div class="d-flex justify-content-start align-items-end h-100">
                                    {% comment %} <h5><span class="badge bg-primary ms-2">New</span></h5> {%endcomment %}
                                    {{product.type.code|safe}}
                                </div>
                            </div>
                            <div class="hover-overlay">
                                <div class="mask" style="background-color: rgba(251, 251, 251, 0.15);"></div>
                            </div>
                        </a>
                    </div>

                    <div class="card-body">
                        <a href="" class="text-reset">
                            <h5 class="card-title mb-3">{{ product.name}}</h5>
                        </a>
                        <a href="" class="text-reset">
                            <p>{{ product.category.name}}</p>
                        </a>
                        <h6 class="mb-3">${{ product.type.code_price | safe }}</h6>
                    </div>

                </div>
            </div>
        {% endfor %}

    </div>
</section>

效果差异

  • 预期效果:页面渲染出带划线的原价和红色字体的折扣价
  • 实际效果:页面直接显示{{product.price | safe}}、{{product.get_price_with_discount() | safe}}这类未解析的字符串

解决方案

Django默认只会解析模板文件中写死的变量,数据库存储的模板代码不会被二次渲染。要实现需求,需要手动编写自定义模板标签来解析这些字符串。

步骤1:创建自定义模板标签

在你的Django应用目录下创建templatetags文件夹,里面新建两个文件:__init__.py(空文件即可)和render_db_template.py,代码如下:

# templatetags/render_db_template.py
from django import template
from django.template import Template, Context

register = template.Library()

@register.simple_tag(takes_context=True)
def render_template(context, template_string):
    # 从当前模板上下文获取product对象
    product = context.get('product')
    # 创建模板实例并传入上下文渲染
    template = Template(template_string)
    return template.render(Context({'product': product}))

步骤2:修改模板使用自定义标签

在services.html开头加载自定义标签,替换原来的|safe用法:

{% load render_db_template %}

<section>
    <div class="text-center container py-5">
        <h4 class="mt-4 mb-5"><strong>畅销品</strong></h4>

        <div class="row">
            {% for product in products %}

            <div class="col-lg-4 col-md-12 mb-4">
                <div class="card">
                    <div class="bg-image hover-zoom ripple ripple-surface ripple-surface-light"
                        data-mdb-ripple-color="light">
                        <img src="{{product.image.url}}" class="w-100" style="height: 500px;" />
                        <a href="#!">
                            <div class="mask">
                                <div class="d-flex justify-content-start align-items-end h-100">
                                    {% render_template product.type.code %}
                                </div>
                            </div>
                            <div class="hover-overlay">
                                <div class="mask" style="background-color: rgba(251, 251, 251, 0.15);"></div>
                            </div>
                        </a>
                    </div>

                    <div class="card-body">
                        <a href="" class="text-reset">
                            <h5 class="card-title mb-3">{{ product.name}}</h5>
                        </a>
                        <a href="" class="text-reset">
                            <p>{{ product.category.name}}</p>
                        </a>
                        <h6 class="mb-3">$ {% render_template product.type.code_price %}</h6>
                    </div>

                </div>
            </div>
        {% endfor %}

    </div>
</section>

注意事项

  • 确保templatetags文件夹结构正确,__init__.py必须存在(可以为空)
  • 自定义标签已处理HTML安全渲染,无需额外添加|safe过滤器
  • 如果数据库中的模板字符串包含其他变量,可在Context中添加对应变量传递

内容的提问来源于stack exchange,提问作者Dhrumil Shah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 04:49:54