Python 使用JSONField()获取非字段错误
我试图使用对Django Rest框架发出补丁请求,但出现以下错误:Python 使用JSONField()获取非字段错误,python,django,django-rest-framework,Python,Django,Django Rest Framework,我试图使用对Django Rest框架发出补丁请求,但出现以下错误: {"image_data": [{"non_field_errors": ["Invalid data"]}] 我知道JSONField()可能会出现一些问题,所以我通过将添加到\u native和从\u native添加,解决了这些问题,但是,我仍然遇到了这个问题。我不认为这里的问题是JSONField(),但仍然值得一提 我相信我在尝试更新相关领域时犯了一些根本性的错误 下面的代码 型号: class Photo(mod
{"image_data": [{"non_field_errors": ["Invalid data"]}]
我知道JSONField()可能会出现一些问题,所以我通过将添加到\u native
和从\u native添加,解决了这些问题,但是,我仍然遇到了这个问题。我不认为这里的问题是JSONField()
,但仍然值得一提
我相信我在尝试更新相关领域时犯了一些根本性的错误
下面的代码
型号:
class Photo(models.Model):
user = models.ForeignKey(AppUser, help_text="Item belongs to.")
image_data = models.ForeignKey("PhotoData", null=True, blank=True)
class PhotoData(models.Model):
thisdata = JSONField()
class ExternalJSONField(serializers.WritableField):
def to_native(self, obj):
return json.dumps(obj)
def from_native(self, value):
try:
val = json.loads(value)
except TypeError:
raise serializers.ValidationError(
"Could not load json <{}>".format(value)
)
return val
class PhotoDataSerializer(serializers.ModelSerializer):
thisdata = ExternalJSONField()
class Meta:
model = PhotoData
fields = ("id", "thisdata")
class PhotoSerializer(serializers.ModelSerializer):
image_data = PhotoDataSerializer()
class Meta:
model = Photo
fields = ("id","user", "image_data")
> payload = {"image_data": {"thisdata": "{}"}}
> requests.patch("/photo/123/",payload )
序列化程序:
class Photo(models.Model):
user = models.ForeignKey(AppUser, help_text="Item belongs to.")
image_data = models.ForeignKey("PhotoData", null=True, blank=True)
class PhotoData(models.Model):
thisdata = JSONField()
class ExternalJSONField(serializers.WritableField):
def to_native(self, obj):
return json.dumps(obj)
def from_native(self, value):
try:
val = json.loads(value)
except TypeError:
raise serializers.ValidationError(
"Could not load json <{}>".format(value)
)
return val
class PhotoDataSerializer(serializers.ModelSerializer):
thisdata = ExternalJSONField()
class Meta:
model = PhotoData
fields = ("id", "thisdata")
class PhotoSerializer(serializers.ModelSerializer):
image_data = PhotoDataSerializer()
class Meta:
model = Photo
fields = ("id","user", "image_data")
> payload = {"image_data": {"thisdata": "{}"}}
> requests.patch("/photo/123/",payload )
我也尝试过:
> payload = {"image_data": [{"thisdata": "{}"}]}
> requests.patch("/photo/123/",payload )
但同样的错误是:
[{“非字段错误”:[“无效数据”]}Django Rest框架关系序列化的最初想法是不更改相关字段的值。
这意味着您的负载应该包含PhotoData
对象的pk
,而不是它的数据集。
这就像在模型中不能将dict分配给外键字段一样
良好(仅适用于本身包含问题的serializers.PrimaryKeyRelatedField):
坏(默认情况下不适用于DRF):
实际上,您提供的数据模型根本不需要PhotoData
(您可以将thisdata
字段移动到Photo
),但假设您有一个特例,即使Python的Zen说特例不足以打破规则。
因此,以下是一些可能的方法:
使用字段序列化程序(您的原始方式)
你现在想做的是可能的,但这是一个非常丑陋的解决方案。
您可以创建一个PhotoDataField
(对我有用,但不准备使用代码,仅用于演示)
并在PhotoSerializer
class PhotoSerializer(serializers.ModelSerializer):
image_data = PhotoDataField(read_only=False, source='image_data')
class Meta:
model = Photo
fields = ("id", "user", "image_data")
因此,请求将很好地工作
payload = {"image_data": '{}'}
resp = requests.patch(request.build_absolute_uri("/api/photo/1/"), payload)
“好”的要求也是如此
photodata = PhotoData.objects.get(pk=1)
payload = {"image_data": photodata.pk}
resp = requests.patch(request.build_absolute_uri("/api/photo/1/"), payload)
在结果中,您将在GET请求中看到“图像数据”:谢谢!这是一个很好的答案。我过分简化了将这些数据作为OP的相关模型的理由。自从你发布了这些数据后,我做了一些研究,对你的推理有了更多的了解。这是一个巨大的帮助。再次感谢
class PhotoDataSerializer(serializers.ModelSerializer):
class Meta:
model = PhotoData
fields = ("id", "thisdata")
class PhotoSerializer(serializers.ModelSerializer):
image_data = PhotoDataSerializer() # or serializers.RelatedField
class Meta:
model = Photo
fields = ("id", "user", "image_data", "test")
from rest_framework import viewsets, routers, generics
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status
# ViewSets define the view behavior.
class PhotoViewSet(viewsets.ModelViewSet):
model = Photo
serializer_class = PhotoSerializer
@action(methods=['PATCH'])
def set_photodata(self, request, pk=None):
photo = self.get_object()
serializer = PhotoDataSerializer(data=request.DATA)
if serializer.is_valid():
if not photo.image_data:
photo.image_data = PhotoData.objects.create()
photo.save()
photo.image_data.thisdata = serializer.data
photo.image_data.save()
return Response({'status': 'ok'})
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
payload = {"thisdata": '{"test": "ok"}'}
resp = requests.patch(request.build_absolute_uri("/api/photo/1/set_photodata/"), payload)