Как назначить поля read_only сериала DRF из представлений - PullRequest
0 голосов
/ 19 апреля 2020

Пример кода

# 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 Ответ

1 голос
/ 19 апреля 2020

pass profile значение в save() метод сериализатора, как

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