Python 使用JSONField()获取非字段错误

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

我试图使用对Django Rest框架发出补丁请求,但出现以下错误:

{"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)