Django Rest Framework保存字典到TextField报错:Not a valid string.
问题分析与解决方案
当然可以把字典保存到TextField中,但你遇到的错误确实是因为TextField默认只接受字符串类型,而你直接传入了字典对象,导致序列化验证失败。下面给你几种可行的解决思路:
方案一:在请求端将字典转为JSON字符串
最简单的方式是在发送POST请求前,把incoming_data对应的字典序列化为JSON字符串。比如如果是Python代码发送请求:
import json import requests data = { # 其他字段... 'incoming_data': json.dumps({"key1":"value1","key2":"value2"}) } requests.post(url, json=data)
如果是前端JavaScript发送请求:
const data = { // 其他字段... incoming_data: JSON.stringify({"key1":"value1","key2":"value2"}) }; fetch(url, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) });
这样后端的序列化器就能直接通过验证,字符串会被正常存入TextField。
方案二:在序列化器中自动处理类型转换
如果不想修改请求端的代码,可以在Django序列化器中自定义字段,自动完成字典和JSON字符串的转换:
import json from rest_framework import serializers from .models import ApiLog class JSONTextField(serializers.Field): def to_internal_value(self, data): # 将输入的字典/列表转为JSON字符串,存入数据库 try: return json.dumps(data) except TypeError: raise serializers.ValidationError("Invalid data: expected a dict or list.") def to_representation(self, value): # 从数据库读取字符串时,转回字典/列表返回给前端 try: return json.loads(value) except (TypeError, json.JSONDecodeError): return value class ApiLogSerializer(serializers.ModelSerializer): incoming_data = JSONTextField() class Meta: model = ApiLog fields = ('incoming_data',)
这样无论前端传的是字典还是合法的JSON字符串,序列化器都能正确处理:存入数据库的是JSON字符串,返回给前端的是结构化的字典。
方案三:改用Django原生的JSONField(推荐)
如果你的Django版本在3.1及以上,更推荐直接把模型中的TextField换成JSONField,Django会自动处理JSON数据的序列化和反序列化,无需额外代码:
修改models.py:
from django.db import models class ApiLog(models.Model): # ...其他字段 incoming_data = models.JSONField('incoming data', null=True, blank=True)
序列化器无需修改:
class ApiLogSerializer(serializers.ModelSerializer): class Meta: model = ApiLog fields = ('incoming_data',)
此时你直接传入字典,序列化器会自动验证并将其存入数据库(底层还是以JSON字符串形式存储,但Django会自动处理类型转换),读取时也会直接返回字典格式的数据,非常方便。
为什么会出现验证错误?
models.TextField对应的序列化字段默认会验证输入是否为字符串类型,你传入的是Python字典(或JSON对象),不符合字段的类型要求,因此触发了"Not a valid string."的验证错误。
内容的提问来源于stack exchange,提问作者Dmitry Korshunov
相关产品推荐
相关产品推荐

