Пример кода
# 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
и явно устанавливать значение профиля ...