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

如何在Django的get_success_message函数中传递字典?

问题根源:SuccessMessageMixin 仅支持字符串类型消息

你遇到的核心问题是:Django 的 SuccessMessageMixin 是专门为返回字符串消息设计的。当你返回字典时,Django 的消息框架会自动把字典转换成字符串(比如变成 "{'color': 'success', 'titulo': 'Película editada', ...}" 这样的文本),所以模板里的 {{ message.color }} 自然取不到值——此时 message 的内容是字符串,而非字典。

下面给你几种可行的解决方案,从快速实现到灵活适配:


方案1:JSON序列化字典,模板中用JS解析(快速落地)

把字典转成JSON字符串传递,再在模板里用JS解析成对象后渲染内容:

视图修改:

import json
from django.contrib.messages import constants as messages
from django.views.generic.edit import UpdateView, SuccessMessageMixin

class PeliculasEdit(SuccessMessageMixin, UpdateView):
    model = Pelicula
    form_class = PeliculaForm
    template_name = "videoclub/peliculas_edit.html"
    success_url = reverse_lazy('peliculas_manage')
    message_data = {
        'color':'success',
        'titulo':'Película editada',
        'mensaje':'La película se ha editado correctamente',
    }

    def get_success_message(self, cleaned_data):
        # 将字典序列化为JSON字符串
        return json.dumps(self.message_data)

模板修改:

{% if messages %}
    {% for message in messages %}
        <!-- 用json_script过滤器安全传递JSON到前端 -->
        {{ message.message|json_script:"toast-data" }}
        <div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
            <div class="toast-header">
                <strong class="me-auto" id="toast-title"></strong>
            </div>
            <div class="toast-body">
                <p id="toast-message"></p>
            </div>
        </div>
        <script>
            // 解析JSON并渲染到DOM
            const toastData = JSON.parse(document.getElementById('toast-data').textContent);
            document.getElementById('toast-title').textContent = toastData.titulo;
            document.getElementById('toast-message').textContent = toastData.mensaje;
            // 给toast添加对应颜色样式
            document.querySelector('.toast').classList.add(`bg-${toastData.color}`);
        </script>
    {% endfor %}
{% endif %}

方案2:利用extra_tags传递元数据(纯后端渲染)

如果不想用JS,可以把额外数据放到消息的extra_tags里,主消息用分隔符拼接,模板里拆分解析:

视图修改:

from django.contrib import messages
from django.views.generic.edit import UpdateView, SuccessMessageMixin

class PeliculasEdit(SuccessMessageMixin, UpdateView):
    model = Pelicula
    form_class = PeliculaForm
    template_name = "videoclub/peliculas_edit.html"
    success_url = reverse_lazy('peliculas_manage')
    message_data = {
        'color':'success',
        'titulo':'Película editada',
        'mensaje':'La película se ha editado correctamente',
    }

    def form_valid(self, form):
        response = super().form_valid(form)
        # 手动添加消息,将颜色放入extra_tags,标题和内容拼接成主消息
        messages.success(
            self.request,
            f"{self.message_data['titulo']}||{self.message_data['mensaje']}",
            extra_tags=self.message_data['color']
        )
        return response

    # 覆盖方法避免重复添加消息
    def get_success_message(self, cleaned_data):
        return ""

模板修改(需自定义split过滤器)

首先在你的app下创建templatetags目录,添加custom_filters.py文件:

from django import template

register = template.Library()

@register.filter
def split(value, sep):
    return value.split(sep)

然后在模板中加载并使用:

{% load custom_filters %}

{% if messages %}
    {% for message in messages %}
        {% with message_parts=message.message|split:"||" %}
        <div class="toast show bg-{{message.tags}}" role="alert" aria-live="assertive" aria-atomic="true">
            <div class="toast-header">
                <strong class="me-auto">{{ message_parts.0 }}</strong>
            </div>
            <div class="toast-body">
                <p>{{ message_parts.1 }}</p>
            </div>
        </div>
        {% endwith %}
    {% endfor %}
{% endif %}

方案3:手动添加消息(最灵活,推荐)

放弃SuccessMessageMixin,直接在form_valid里添加带完整元数据的消息,这是最贴合Django消息框架设计的方式:

视图修改:

from django.contrib import messages
from django.views.generic.edit import UpdateView

class PeliculasEdit(UpdateView):
    model = Pelicula
    form_class = PeliculaForm
    template_name = "videoclub/peliculas_edit.html"
    success_url = reverse_lazy('peliculas_manage')
    message_data = {
        'color':'success',
        'titulo':'Película editada',
        'mensaje':'La película se ha editado correctamente',
    }

    def form_valid(self, form):
        response = super().form_valid(form)
        # 用extra_tags传递所有元数据,键值对用空格分隔
        messages.success(
            self.request,
            self.message_data['mensaje'],
            extra_tags=f"color:{self.message_data['color']} titulo:{self.message_data['titulo']}"
        )
        return response

模板修改:

{% if messages %}
    {% for message in messages %}
        {% with tag_parts=message.extra_tags.split %}
            {% comment %} 解析extra_tags中的元数据 {% endcomment %}
            {% assign color = "" %}
            {% assign titulo = "" %}
            {% for part in tag_parts %}
                {% if part starts with "color:" %}
                    {% color = part|cut:"color:" %}
                {% elif part starts with "titulo:" %}
                    {% titulo = part|cut:"titulo:" %}
                {% endif %}
            {% endfor %}
            <div class="toast show bg-{{color}}" role="alert" aria-live="assertive" aria-atomic="true">
                <div class="toast-header">
                    <strong class="me-auto">{{ titulo }}</strong>
                </div>
                <div class="toast-body">
                    <p>{{ message }}</p>
                </div>
            </div>
        {% endwith %}
    {% endfor %}
{% endif %}

总结

最推荐方案3,它不需要序列化/反序列化操作,完全利用Django消息框架的原生特性,代码更清晰也更容易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:32:37