存储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
相关产品推荐
相关产品推荐

