rest framework how to create optional nested object?

DRF 3.1.3,Django 1.8.3

i have several model just like following code:

Post

class Post(models.Model):
    class Meta:
        ordering = ['-updated_time']

    author = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='+')
    circle = models.ForeignKey('circle')

    TYPE_CHOICES = (
        ('M', _('Members')),
        ('O', _('Org')),
    )
    type = models.CharField(_('Type'), choices=TYPE_CHOICES, default='M', max_length=1, help_text=u"帖子类型,是成员发帖,还是组织发帖?")

    created_time = models.DateTimeField(auto_now_add=True, db_index=True, editable=False)
    updated_time = models.DateTimeField(auto_now=True, db_index=True, editable=False)

    like = models.PositiveIntegerField(default=0)

    comments = GenericRelation(PostComment)
    images = GenericRelation(PostImage)
    likes = GenericRelation(PostLike)

    is_removed = models.BooleanField(_('Is Removed'), default=False, db_index=True)

RichPost

class RichPost(models.Model):
    title = models.CharField(max_length=100)
    summary = models.TextField(max_length=560)
    content = models.TextField(max_length=16000)

    post = models.OneToOneField(Post, related_name='rich')

SimplePost

class SimplePost(models.Model):
    content = models.TextField(max_length=560)
    post = models.OneToOneField(Post, related_name='simple')

PostSerializer

class PostSerializer(serializers.ModelSerializer):
    images = PostImageSerializer(many=True)

    simple = SimplePostSerializer(many=False)
    rich = RichPostSerializer(many=False)

    is_liked = serializers.SerializerMethodField('is_liked_by_user')

    def create(self, validated_data):
        simple = validated_data.pop('simple')
        rich = validated_data.pop('rich')
        post = Post.objects.create(**validated_data)
        return post

    def is_liked_by_user(self, obj):
        request = self.context['request']
        obj_type = ContentType.objects.get_for_model(obj)
        if PostLike.objects.filter(author=request.user, content_type__pk=obj_type.id, object_id=obj.id).exists():
            return True
        else:
            return False

    class Meta:
        model = Post
        fields = ('id', 'author', 'circle', 'type', 'created_time', 'updated_time', 'like', 'is_removed',
                  'images', 'comments_count', 'is_liked', 'simple', 'rich')
        read_only_fields = ('comments_count', 'is_liked', 'created_time', 'updated_time', 'like', 'author')

Post belongs one of RichPost and SimplePost.

when i created the Post,both of them are required.

for instance,when i sent simple.content,the rich.title,rich.summary,rich.content are required.

then,i found the api document: writable-nested-representations

i overrode .create() methods

but it does not been invoked at all,is_valid() before attempting to access the validated data, or save an object instance

Anyone has an idea?Thanks for any answer.

Answers


Both rich and simple posts are required in your serializer. You should make them optional. If you need at least one of them to be required, you can do that in validate():

class PostSerializer(serializers.ModelSerializer):
    simple = SimplePostSerializer(required=False)
    rich = RichPostSerializer(required=False)
    ...
    def validate(self, data):
        data = super(PostSerializer, self).validate(data)
        if not any([data.get('simple'), data.get('rich')]):
            raise serializers.ValidationError('Either simple or rich is required')
        return data

When i from DRF 3.1.3 upgraded to DRF 3.2.2,I don't know what was going on,it just works :(

It pass through .is_valid() to reach the .create().


Need Your Help

Layout setup with fragments

android android-layout android-fragments

I've just started converting my apps to use fragments. I have a ListView activity and a "Details" activity, which the user goes to after selecting an item in the Listview. I've converted them to

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.