DRF 序列化外键返回对象,而不是 ID

时间:2021-07-06 21:58:08

标签: python django django-rest-framework

我有一个一对多的关系。一个建筑和许多相机。 我想返回 CameraSerializer 中的所有建筑对象字段

问题

当我执行 POST 请求时(创建新的 Camera 对象)

{
    "name": "CameraName",
    "url": "CameraUrl",
    "building": 2
    
}

我有一个错误

{
    "building": {
        "nonFieldErrors": [
            "Invalid data. Expected a dictionary, but got int."
        ]
    }
}

错误原因 -- Django 需要 FULL Construction 对象,但我只想设置 ID

如何修复错误?

models.py

class Construction(models.Model):
    """ Объект строительства"""
    developer = models.ForeignKey(
        Developer, related_name="constructions", on_delete=models.CASCADE
    )
    name = models.CharField(max_length=100)
    plan_image = models.ImageField(upload_to=name_image, blank=True, null=True)
    ...

    def __str__(self):
        return self.name

class Camera(models.Model):
    building = models.ForeignKey(
        Construction, related_name="cameras", on_delete=models.CASCADE
    )
    name = models.CharField(max_length=100)
    url = models.CharField(max_length=100)
    ...

    def __str__(self):
        return self.name

serializers.py

class ConstructionSerializer(serializers.ModelSerializer):
    coordinates = MyPointField()
    deadline = serializers.DateTimeField(format=TIME_FORMAT)
    cameras_number = serializers.SerializerMethodField()
    developer_name = serializers.SerializerMethodField()
    events = serializers.SerializerMethodField()

    class Meta:
        model = Construction
        fields = (
            'id', 'developer', 'developer_name', 'name', 'plan_image', 'address', 'coordinates', 'deadline',
            'workers_number', 'machines_number', 'cameras_number', 'events'
        )
        read_only_fields = ('workers_number', 'machines_number', 'cameras_number', 'events')

    
    def create(self, validated_data):
        instance = super().create(validated_data=validated_data)
        return instance


class CameraSerializer(serializers.ModelSerializer):
    frames = FrameSerializer(many=True, read_only=True)
    building = ConstructionSerializer()

    class Meta:
        model = Camera
        fields = (
            'id', 'building', 'name', 'url', 'zone_id_x', 'zone_id_y',
            'proc_id', 'path_frames', 'frames'
        )
        read_only_fields = ('proc_id', 'path_frames', 'frames')
    
    def create(self, validated_data):
        instance = super().create(validated_data=validated_data)
        instance.set_proc_id()
        instance.set_path_frame()
        return instance

views.py

class CameraView(viewsets.ModelViewSet):
    serializer_class = CameraSerializer
    queryset = Camera.objects.all()

    def get_camera_create_serializer(self, *args, **kwargs):
        kwargs["context"] = self.get_serializer_context()
        return self.serializer_class(*args, **kwargs)

    def create(self, request, *args, **kwargs):
        serializer = self.get_camera_create_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        response = {"result": serializer.data}
        return Response(
            response, status=status.HTTP_201_CREATED, headers=headers
        )

0 个答案:

没有答案