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

如何通过POST请求将Django对象从模板传递至视图并正确序列化?

解决Django复选框传递对象序列化无效JSON的问题

我尝试通过以下方式将复选框的值传递至views.py:
my_template.html

<input type="checkbox" name="playlist" value='{{ playlist }}'>

views.py

json_str_list = request.POST.getlist('playlist')

json_str_list中的序列化内容如下:

'{\'id\': \'UUkfDws3roWo1GaA3pZUzfIQ\', \'title\': "Item 1", \'created_on\': datetime.datetime(2023, 6, 12, 20, 44, 41, 392273, tzinfo=datetime.timezone.utc)}'

这显然不是有效的JSON字符串。我该如何调整Django中对象的序列化方式?
尝试用json.loads()反序列化为对象时,出现以下错误:

属性名必须用双引号包裹


你现在的问题出在直接把Django对象渲染到value属性里,这本质是调用了对象的__str__或__repr__方法,得到的不是标准JSON格式——不仅属性名用了单引号,datetime对象也保留了Python原生格式,自然无法被json.loads解析。

可以通过以下几种方式解决:

1. 在视图中预序列化对象,传递标准JSON字符串到模板

在渲染模板的视图里,用Django的序列化工具或者Python的json模块把对象转成标准JSON:

步骤1:修改视图(序列化对象)

from django.core import serializers
import json
from django.shortcuts import render

def your_view(request):
    # 假设playlists是你要传递的查询集或单个对象
    playlists = Playlist.objects.all()
    serialized_playlists = []
    for playlist in playlists:
        # 用Django serializer转成字典,再补充id字段
        data = serializers.serialize('python', [playlist])[0]['fields']
        data['id'] = playlist.id
        # 将datetime转成ISO格式字符串,符合JSON规范
        data['created_on'] = playlist.created_on.isoformat()
        # 转成标准JSON字符串
        serialized_playlists.append(json.dumps(data))
    return render(request, 'my_template.html', {'playlists': serialized_playlists})

步骤2:修改模板(渲染JSON字符串)

模板里直接使用序列化后的JSON字符串,用escapejs过滤器处理特殊字符,避免HTML渲染时出错:

{% for playlist_json in playlists %}
<input type="checkbox" name="playlist" value="{{ playlist_json|escapejs }}">
{% endfor %}

2. 只传递对象ID,在后端重新查询(更简单高效)

如果不需要传递完整对象数据,只传ID是更轻量、安全的方案:

模板修改

<input type="checkbox" name="playlist_id" value="{{ playlist.id }}">

后端处理

playlist_ids = request.POST.getlist('playlist_id')
# 根据ID批量查询对象
playlists = Playlist.objects.filter(id__in=playlist_ids)

这种方式避免了序列化/反序列化的麻烦,也不会把敏感数据暴露在前端。

3. 自定义模型的JSON序列化方法

如果需要频繁序列化该模型,可以在模型类中添加方法直接返回标准JSON:

import json
from django.db import models

class Playlist(models.Model):
    id = models.CharField(max_length=100, primary_key=True)
    title = models.CharField(max_length=200)
    created_on = models.DateTimeField(auto_now_add=True)

    def to_json(self):
        data = {
            'id': self.id,
            'title': self.title,
            'created_on': self.created_on.isoformat()
        }
        return json.dumps(data)

然后在模板里直接调用:

<input type="checkbox" name="playlist" value="{{ playlist.to_json|escapejs }}">

为什么原来的方式不行?

直接渲染{{ playlist }}得到的是Python对象的字符串表示,和标准JSON有两个核心冲突:

  • JSON要求属性名必须用双引号,而Python对象的字符串表示用单引号
  • datetime属于Python原生类型,无法被JSON直接解析,必须转成字符串格式(比如ISO格式)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:53:18