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

存储react-draft-wysiwyg产出JSON的Django模型字段选型方案

实现方案

1. Django模型设计

你拿到的是Draft.js原生的ContentState结构化JSON,不需要拆表存储,直接用JSONField存原始结构即可,同时可以额外存一份转换后的纯文本/HTML,方便做全文检索、列表页摘要展示,避免每次查询都要解析大段JSON。
模型代码参考:

from django.db import models
# Django 3.1+ 版本内置支持跨数据库的JSONField,直接从models导入即可
# 低版本PostgreSQL环境可以用 from django.contrib.postgres.fields import JSONField

class WysiwygContent(models.Model):
    # 存储Draft编辑器输出的完整原始结构,就是你贴的包含blocks、entityMap的JSON对象
    draft_raw = models.JSONField(verbose_name="Draft编辑器原始数据")
    # 可选字段:存储自动提取的纯文本,用于全文检索、列表摘要
    plain_text = models.TextField(verbose_name="纯文本内容", blank=True, default="")
    # 可选字段:存储自动转换的HTML,服务端直出内容场景可以使用
    html_content = models.TextField(verbose_name="渲染后HTML", blank=True, default="")
    create_time = models.DateTimeField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)

注意:如果使用MySQL 5.7以下、旧版SQLite这类不支持原生JSON类型的数据库,JSONField会自动转成文本格式存储,不影响正常读写,只是无法做数据库层面的JSON字段查询,存储数据完全没有问题。

2. DRF序列化器配置

序列化器不需要对JSON结构做特殊拆分校验,直接接收对象即可,可以在序列化器层自动完成纯文本、HTML的转换,不需要前端传这两个字段:

from rest_framework import serializers
from .models import WysiwygContent
# 先安装依赖:pip install draftjs-exporter,用于服务端把Draft结构转成HTML
from draftjs_exporter.html import HTML as DraftHtmlExporter

# 按你编辑器实际支持的块、样式配置导出规则即可
exporter_config = {
    "block_map": {
        "header-three": {"element": "h3"},
        "unstyled": {"element": "p"},
        # 其他用到的块类型比如有序列表、引用块、代码块自行补充映射
    },
    "style_map": {
        # 行内样式比如颜色、字号、字体的映射按需配置
    }
}
exporter = DraftHtmlExporter(exporter_config)

class WysiwygContentSerializer(serializers.ModelSerializer):
    class Meta:
        model = WysiwygContent
        fields = ["id", "draft_raw", "plain_text", "html_content", "create_time", "update_time"]
        read_only_fields = ["plain_text", "html_content"] # 两个衍生字段后端自动生成,禁止前端修改

    def create(self, validated_data):
        draft_raw = validated_data["draft_raw"]
        # 提取所有块的文本拼接成纯文本
        validated_data["plain_text"] = "\n".join([block.get("text", "") for block in draft_raw.get("blocks", [])])
        # 导出HTML内容
        validated_data["html_content"] = exporter.render(draft_raw)
        return super().create(validated_data)

    def update(self, instance, validated_data):
        if "draft_raw" in validated_data:
            draft_raw = validated_data["draft_raw"]
            validated_data["plain_text"] = "\n".join([block.get("text", "") for block in draft_raw.get("blocks", [])])
            validated_data["html_content"] = exporter.render(draft_raw)
        return super().update(instance, validated_data)

3. 视图层配置

直接用常规的ModelViewSet即可,天然支持GET、PATCH、POST、DELETE全量请求方法,不需要额外做特殊处理:

from rest_framework.viewsets import ModelViewSet
from .models import WysiwygContent
from .serializers import WysiwygContentSerializer

class WysiwygContentViewSet(ModelViewSet):
    queryset = WysiwygContent.objects.all()
    serializer_class = WysiwygContentSerializer

配上路由之后接口就可以直接调用了。

4. 对接注意事项

  • 前端提交数据时,不要传JSON.stringify之后的字符串,直接传解析后的JS对象即可,DRF会自动完成JSON解析
  • 前端回显内容时,直接把GET接口返回的draft_raw字段传给编辑器做初始化即可,不需要做额外格式转换
  • 如果编辑器用到了图片、链接、提及这类实体,只要在draftjs-exporter的配置里补充对应的实体映射规则,导出的HTML就不会丢失内容
  • 不要图省事直接把编辑器内容转成HTML存在TextField里,后续编辑时把HTML反向转回Draft结构很容易丢失格式、出现兼容问题,存储原始JSON结构是最稳妥的方案,后续做内容导出、渲染规则调整都不会受限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:54:22