Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django rest framework create nested objects "Models" by POST

I'm trying POST a new a Nested Object, the problem is just create the "top" object (Playlist), but don't create the "ChannelItem"...

My Models:

class Playlist(models.Model):     provider = models.IntegerField()     channel_id = models.CharField(max_length=100)     channel_version = models.CharField(blank=True, max_length=100)     start = models.DateTimeField()     url = models.CharField(max_length=500)   class ChannelItem(models.Model):     playlist = models.ForeignKey(Playlist, editable=False, related_name='channelitems')     content_id = models.CharField(max_length=100)     content_version = models.CharField(blank=True, max_length=100) 

My Serializer:

class ChannelItemSerializer(serializers.ModelSerializer):     class Meta:         model = ChannelItem         fields = ('content_id', 'content_version')         exclude = ('id')         depth = 1   class PlaylistSerializer(serializers.ModelSerializer):      class Meta:         model = Playlist         fields = ('id', 'provider', 'channel_id', 'channel_version', 'start',                    'url', 'channelitems')         depth = 2  channelitems = ChannelItemSerializer() 

I use the curl to post the following data :

'{"provider":125,"channel_id":"xyz", "channel_version":"xsqt",  "start":"2012-12-17T11:04:35","url":"http://192.168.1.83:8080/maaaaa", "channelitems":[{"content_id":"0.flv", "content_version":"ss"}, {"content_id":"1.flv","content_version":"ss"}]}' http://localhost:8000/playlist_scheduler/playlists/ 

I receive the message:

HTTP/1.1 201 CREATED Content-Type: application/json Transfer-Encoding: chunked Date: Mon, 17 Dec 2012 20:12:54 GMT Server: 0.0.0.0  {"id": 25, "provider": 125, "channel_id": "xyz", "channel_version": "xsqt", "start":"2012-12-17T11:04:35", "url": "http://localhost:8080/something", "channelitems": []} 
like image 387
skopp Avatar asked Dec 17 '12 20:12

skopp


2 Answers

Nested representations do not currently support read-write, and should instead be read-only.

You should probably look into using a flat representation instead, using pk or hyperlinked relations.

If you need the nested representation, you may want to consider having two separate endpoints - a flat writable endpoint, and a nested read-only endpoint.

like image 120
Tom Christie Avatar answered Sep 21 '22 05:09

Tom Christie


If someone needs a quick-and-dirty solution for that, I came up with this one I'll be temporary using in a project:

class NestedManyToManyField(serializers.WritableField):     def to_native(self, value):         serializer = self.Meta.serializer(value.all(), many=True, context=self.context)         return serializer.data     def from_native(self, data):         serializer = self.Meta.serializer(data=data, many=True, context=self.context)         serializer.is_valid()         serializer.save()         return serializer.object     class Meta:         serializer = None 

Then create your own subclass of NestedManyToManyField:

class TopicNestedSerializer(NestedManyToManyField):     class Meta:         serializer = MyOriginalSerializer 

An example of MyOriginalSerializer:

class MyOriginalSerializer(serializers.ModelSerializer):     class Meta:         model = models.MyModel         fields = ('id', 'title',) 

This works fine for me so far. But be aware there are clean fixes coming:

  • https://github.com/tomchristie/django-rest-framework/issues/960
  • https://github.com/tomchristie/django-rest-framework/pull/817
like image 44
Micha Mazaheri Avatar answered Sep 20 '22 05:09

Micha Mazaheri