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

Django3.2.12用django-mjml报错:Context对象无render_context属性

问题

运行Django==3.2.12,使用django-mjml生成渲染后的模板字符串,此前功能正常,现在出现错误:'Context' object has no attribute 'render_context'。

相关代码

import uuid
from django.db import models
from django.template import Template, Context
from django.urls import reverse


class EmailTemplate(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField(max_length=255, unique=True)
    uuid = models.UUIDField(default = uuid.uuid4)
    mjml_template = models.TextField(blank=True)
    html_template = models.TextField(blank=True)

    class Meta:
        ordering = ['name', ]
        verbose_name = 'Template'
        verbose_name_plural = 'Templates'

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('pages:emailing', kwargs={'slug': self.slug, 'uuid': self.uuid})

    def save(self, *args, **kwargs):

        mjml_open = '{% load mjml %}{% mjml %}'
        mjml_close = '{% endmjml %}'

        verbatum_open = '{% verbatim %}{{'
        verbatum_close = '}}{% endverbatim %}'

        verbatum = self.mjml_template.replace('{{', verbatum_open)
        verbatum = verbatum.replace('}}', verbatum_close)
        verbatum = mjml_open + verbatum + mjml_close

        template = Template(verbatum)
        context = Context({})

        passed = False
        try:
            self.html_template = template.render(context)
            passed = True
        except Exception as err:
            self.html_template = str(err)

        if passed:
            image_categories = ImageCategory.objects.filter(templates=self)
            for image_category in image_categories:
                for image in image_category.get_images():
                    tag = '[~ ' + image.slug + ' ~]'
                    swap = self.html_template
                    swap = swap.replace(tag, image.image.url)
                    self.html_template = swap

            resource_categories = ResourceCategory.objects.filter(templates=self)
            for resource_category in resource_categories:
                for resource in resource_category.get_resources():
                    tag = '[~ ' + resource.slug + ' ~]'
                    swap = self.html_template
                    swap = swap.replace(tag, resource.resource)
                    self.html_template = swap

        super(EmailTemplate, self).save(*args, **kwargs)

报错回溯

Internal Server Error: /admin/emailing/emailtemplate/1/change/
Traceback (most recent call last):
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/contrib/admin/options.py", line 616, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/contrib/admin/sites.py", line 232, in inner
    return view(request, *args, **kwargs)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/contrib/admin/options.py", line 1660, in change_view
    return self.changeform_view(request, object_id, form_url, extra_context)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/contrib/admin/options.py", line 1540, in changeform_view
    return self._changeform_view(request, object_id, form_url, extra_context)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/contrib/admin/options.py", line 1586, in _changeform_view
    self.save_model(request, new_object, form, not add)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/contrib/admin/options.py", line 1099, in save_model
    obj.save()
  File "/Applications/MAMP/htdocs/mjml/emailing/models.py", line 42, in save
    self.html_template = template.render(context)
  File "/Users/sbrown/.local/share/virtualenvs/mjml-NNm5TF3H/lib/python3.9/site-packages/django/template/base.py", line 166, in render
    with context.render_context.push_state(self):
AttributeError: 'Context' object has no attribute 'render_context'

解决方案

这个错误的核心原因是:Django 3.2的模板渲染API要求上下文对象具备render_context属性,手动创建的Context实例不符合该要求。

有两种简单的修复方式:

方式一:直接传递字典作为上下文

无需手动创建Context对象,直接将字典传入template.render()方法,Django会自动处理上下文的创建:

# 替换原来的context = Context({})和template.render(context)
self.html_template = template.render({})

方式二:确保使用正确的上下文类

如果需要显式创建上下文,可直接使用django.template.context.Context(虽然Django 3.2中from django.template import Context已指向该类,但环境中可能存在导入混淆)。不过在model的save方法中无request对象,因此更推荐方式一。

另外,建议检查django-mjml版本是否兼容Django 3.2,可升级至最新稳定版的django-mjml包。


内容的提问来源于stack exchange,提问作者Stephen Brown

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 03:15:42