The initial idea for serializing Django Rest Framework relationships is to not change the values โโof the related fields. This means that your payload should contain the pk object of the PhotoData object, not the dataset for it. As with models, you cannot assign a dict to a foreign key field.
Good (only works with serializers.PrimaryKeyRelatedField, which contains the problems themselves):
payload = {"image_data": 2}
Bad (does not work in DRF by default):
payload = {"image_data": {'thisdata': '{}'}}
In fact, the data model you provided does not need PhotoData at PhotoData (you can move the thisdata field to Photo ), but suppose you have a special case, even when Zen of Python says Special cases aren't special enough to break the rules. .
So, here are a few possible ways:
Using field serializers (your original way)
What you want to do now is a possible but very ugly decision. You can create a PhotoDataField (works for me, but not ready to use code, just for demonstration)
class PhotoDataField(serializers.PrimaryKeyRelatedField): def field_to_native(self, *args): """ Use field_to_native from RelatedField for correct `to_native` result """ return super(serializers.RelatedField, self).field_to_native(*args)
and use it in PhotoSerializer
class PhotoSerializer(serializers.ModelSerializer): image_data = PhotoDataField(read_only=False, source='image_data') class Meta: model = Photo fields = ("id", "user", "image_data")
so the request will work well
payload = {"image_data": '{}'} resp = requests.patch(request.build_absolute_uri("/api/photo/1/"), payload)
and a "good" request also
photodata = PhotoData.objects.get(pk=1) payload = {"image_data": photodata.pk} resp = requests.patch(request.build_absolute_uri("/api/photo/1/"), payload)
and as a result you will see in the GET request "image_data": <photodata thisdata value>,
But even if you fix the validation problems with this approach, it will still be a huge pain in the ass, as you can see from my code (this is just what DRF can offer you when you want to โdisrupt the normal workflowโ, Tastypie offers more )
Normalize code and use @action (recommended)
class PhotoDataSerializer(serializers.ModelSerializer): class Meta: model = PhotoData fields = ("id", "thisdata") class PhotoSerializer(serializers.ModelSerializer): image_data = PhotoDataSerializer()
and now define a specific method in your api view that you can use to set the data for any photo
from rest_framework import viewsets, routers, generics from rest_framework.decorators import action from rest_framework.response import Response from rest_framework import status
Now you can make almost the same request as now, but you have much more extensibility and separation of duties in the code. See URL , it is added when you have a method processed by @action.
payload = {"thisdata": '{"test": "ok"}'} resp = requests.patch(request.build_absolute_uri("/api/photo/1/set_photodata/"), payload)
Hope this helps.