Example code
# 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__'
My solution
# 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)
Example call
curl -X POST http://localhost:8000/profiles/4/photos/ --form image=@photo_image.jpg
Expected behavior
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",
....
}
When passing photo image to endpoint /profile/<int:pk>/photos/
, Photo's ( read_only=True
) profile field have been set by extracted <int:pk>
view parameter.
Question
Is there more elegant way to achieve this? I don't feel comfortable accessing serializer.validated_data
and explicitly set profile value...
pass profile
value in save()
method of serializer, as
...
elif request.method == 'POST':
serializer = self.get_serializer(data=request.data)
serializer.is_valid()
return Response(serializer.data)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.