如何从视图中分配DRF串行器只读字段

时间:2020-04-19 15:05:36

标签: python django django-rest-framework

示例代码

# models.py
class Profile(models.Model):
    first_name = models.CharField(max_length=64)
    last_name = models.CharField(max_length=64)
    ...

class Photo(models.Model):
    image = models.ImageField(upload_to='photos')
    profile = models.ForeignKey('Profile', on_delete=models.CASCADE, related_name='photos')
    ...

# serializers.py
class ProfileSerializer(serializers.ModelSerializer):
    photos = serializers.HyperlinkedRelatedField(many=True, view_name='photo-detail', read_only=True)

    class Meta:
        model = Profile
        fields = '__all__'

class PhotoSerializer(serializers.ModelSerializer):
    # How to assign this implicitly from view?
    profile = PrimaryKeyRelatedField(read_only=True)

    class Meta:
        model = Face
        fields = '__all__'

我的解决方案

# views.py
class ProfileViewSet(viewsets.ModelViewSet):
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializer

    @action(methods=['GET', 'POST'], detail=True, serializer_class=FaceSerializer)
    def photos(self, request, *args, **kwargs):
        profile = self.get_object()
        if request.method == 'GET':
            ...
        elif request.method == 'POST':
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid()
            # accessing validated_data
            # explicitly set profile read_only field
            serializer.validated_data['profile'] = profile
            self.perform_create(serializer)
            return Response(serializer.data)

示例呼叫

curl -X POST http://localhost:8000/profiles/4/photos/ --form image=@photo_image.jpg

预期的行为

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 123,
    "profile": 4,
    "image": "http://localhost:9000/media/photos/photo_image.jpg",
    ....
}

将照片图像传递到端点/profile/<int:pk>/photos/时,已通过提取的read_only=True视图参数设置了照片的(<int:pk>)配置文件字段。

问题

有没有更优雅的方法来实现这一目标?访问serializer.validated_data并显式设置配置文件值...

1 个答案:

答案 0 :(得分:1)

通过 profile 序列化方法中的

传递 save() 值,如

...
elif request.method == 'POST':
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid()
    serializer.save(profile=profile)
    return Response(serializer.data)