美文网首页
Django REST Framework的可写嵌套模型序列化程

Django REST Framework的可写嵌套模型序列化程

作者: 鹏ve | 来源:发表于2018-10-19 16:09 被阅读0次
    DRF可写的嵌套(DRF Writable Nested)

    “DRF Writable Nested”是Django REST框架的可写嵌套模型序列化器,它允许您使用相关嵌套数据创建/更新模型。
    支持下列关系:
    OneToOne (direct/reverse)-----一对一(直接的/反向)
    ForeignKey (direct/reverse)-----一对多(直接的/反向)
    ManyToMany (direct/reverse excluding m2m relations with through model)-----多对多(直接/反向不包括通过模型的m2m关系)
    GenericRelation (this is always only reverse)-----一般关系(这总是反过来的)

    Requirements(需求)

    Python (2.7, 3.5, 3.6)
    Django (1.9, 1.10, 1.11, 2.0)
    djangorestframework (3.5+)

    Installation(安装)
    pip install drf-writable-nested
    
    Usage(用法)

    例如,对于以下模型结构:

    from django.db import models
    
    
    class Site(models.Model):
        url = models.CharField(max_length=100)
    
    
    class User(models.Model):
        username = models.CharField(max_length=100)
    
    
    class AccessKey(models.Model):
        key = models.CharField(max_length=100)
    
    
    class Profile(models.Model):
        sites = models.ManyToManyField(Site)
        user = models.OneToOneField(User)
        access_key = models.ForeignKey(AccessKey, null=True)
    
    
    class Avatar(models.Model):
        image = models.CharField(max_length=100)
        profile = models.ForeignKey(Profile, related_name='avatars')
    

    我们应该创建以下序列化器列表:

    from rest_framework import serializers
    from drf_writable_nested import WritableNestedModelSerializer

    class AvatarSerializer(serializers.ModelSerializer):
        image = serializers.CharField()
    
        class Meta:
            model = Avatar
            fields = ('pk', 'image',)
    
    
    class SiteSerializer(serializers.ModelSerializer):
        url = serializers.CharField()
    
    class Meta:
        model = Site
        fields = ('pk', 'url',)
    
    
    class AccessKeySerializer(serializers.ModelSerializer):
    
        class Meta:
            model = AccessKey
            fields = ('pk', 'key',)
    
    
    class ProfileSerializer(WritableNestedModelSerializer):
        # Direct ManyToMany relation
        sites = SiteSerializer(many=True)
    
        # Reverse FK relation
        avatars = AvatarSerializer(many=True)
    
        # Direct FK relation
        access_key = AccessKeySerializer(allow_null=True)
    
        class Meta:
            model = Profile
            fields = ('pk', 'sites', 'avatars', 'access_key',)
    
    
    class UserSerializer(WritableNestedModelSerializer):
        # Reverse OneToOne relation
        profile = ProfileSerializer()
    
        class Meta:
            model = User
            fields = ('pk', 'profile', 'username',)
    

    另外,如果您想只支持创建或更新逻辑,您可以使用这个包中的NestedCreateMixin或NestedUpdateMixin。
    例如,我们可以将以下带有相关嵌套字段的数据传递给我们的主序列化器:

    data = {
        'username': 'test',
        'profile': {
            'access_key': {
                'key': 'key',
            },
            'sites': [
                {
                    'url': 'http://google.com',
                },
                {
                    'url': 'http://yahoo.com',
                },
            ],
            'avatars': [
                {
                    'image': 'image-1.png',
                },
                {
                    'image': 'image-2.png',
                },
            ],
        },
    }
    
    user_serializer = UserSerializer(data=data)
    user_serializer.is_valid(raise_exception=True)
    user = user_serializer.save()
    

    这个序列化器将自动创建所有嵌套的关系,我们将收到一个完整的实例,其中包含已填充的数据。

    user_serializer = UserSerializer(instance=user)
    print(user_serializer.data)
    

    {
        'pk': 1,
        'username': 'test',
        'profile': {
            'pk': 1,
            'access_key': {
                'pk': 1,
                'key': 'key'
            },
            'sites': [
                {
                    'pk': 1,
                    'url': 'http://google.com',
                },
                {
                    'pk': 2,
                    'url': 'http://yahoo.com',
                },
            ],
            'avatars': [
                {
                    'pk': 1,
                    'image': 'image-1.png',
                },
                {
                    'pk': 2,
                    'image': 'image-2.png',
                },
            ],
        },
    }
    

    还可以通过调用基序列化器的save方法将值传递给嵌套的序列化器。这些kwarg必须是dict类型。

    # user_serializer created with 'data' as above
    user = user_serializer.save(
        profile={
            'access_key': {'key': 'key2'},
        },
    )
    print(user.profile.access_key.key)
    

    'key2'
    

    注意:相同的值将用于所有嵌套实例,比如默认值,但是优先级更高。
    已知的解决方案问题
    更新时带有唯一字段的嵌套序列化器的验证问题
    我们有一种特殊的mixin单字段smixin可以解决这个问题。mixin将uniquevalidator从验证阶段移动到保存阶段。
    如果你想知道更多的细节,你可以阅读相关的问题和文章:
    https://github.com/beda-software/drf-writable-nested/issues/1 http://www.django-rest-framework.org/api-guide/validators/#updating-nested-serializers
    使用的例子:

    class Child(models.Model):
        field = models.CharField(unique=True)
    
    
    class Parent(models.Model):
        child = models.ForeignKey('Child')
    
    
    class ChildSerializer(UniqueFieldsMixin, serializers.ModelSerializer):
        class Meta:
            model = Child
    
    
    class ParentSerializer(NestedUpdateMixin, serializers.ModelSerializer):
        child = ChildSerializer()
    
        class Meta:
            model = Parent
    

    注意:UniqueFieldsMixin必须仅应用于具有唯一字段的序列化程序。

    Mixin ordering
    当您同时使用mixin (UniqueFieldsMixin和NestedCreateMixin或NestedUpdateMixin)时,您应该将UniqueFieldsMixin放在前面。

    例如:

    class ChildSerializer(UniqueFieldsMixin, NestedUpdateMixin,
            serializers.ModelSerializer):

    相关文章

      网友评论

          本文标题:Django REST Framework的可写嵌套模型序列化程

          本文链接:https://www.haomeiwen.com/subject/owzyzftx.html