微信小程序列表开发全面详解及实际操作步骤
1346
2022-10-14
Django REST Framework的可写嵌套模型序列化程序
DRF Writable Nested
This is a writable nested model serializer for Django REST Framework which allows you to create/update your models with related nested data.
The following relations are supported:
OneToOne (direct/reverse)ForeignKey (direct/reverse)ManyToMany (direct/reverse excluding m2m relations with through model)GenericRelation (this is always only reverse)
Requirements
Python (3.5, 3.6, 3.7, 3.8)Django (2.2, 3.0)djangorestframework (3.8+)
Installation
pip install drf-writable-nested
Usage
For example, for the following model structure:
from django.db import modelsclass 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')
We should create the following list of serializers:
from rest_framework import serializersfrom drf_writable_nested.serializers import WritableNestedModelSerializerclass 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',)
Also, you can use NestedCreateMixin or NestedUpdateMixin from this package if you want to support only create or update logic.
For example, we can pass the following data with related nested fields to our main serializer:
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()
This serializer will automatically create all nested relations and we receive a complete instance with filled data.
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', }, ], },}
It is also possible to pass through values to nested serializers from the call to the base serializer's save method. These kwargs must be of type dict. E g:
# user_serializer created with 'data' as aboveuser = user_serializer.save( profile={ 'access_key': {'key': 'key2'}, },)print(user.profile.access_key.key)
'key2'
Note: The same value will be used for all nested instances like default value but with higher priority.
Known problems with solutions
Validation problem for nested serializers with unique fields on update
We have a special mixin UniqueFieldsMixin which solves this problem. The mixin moves UniqueValidator's from the validation stage to the save stage.
If you want more details, you can read related issues and articles: https://github.com/beda-software/drf-writable-nested/issues/1 http://django-rest-framework.org/api-guide/validators/#updating-nested-serializers
Example of usage:
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 = Childclass ParentSerializer(NestedUpdateMixin, serializers.ModelSerializer): child = ChildSerializer() class Meta: model = Parent
Note: UniqueFieldsMixin must be applied only on serializer which has unique fields.
Mixin ordering
When you are using both mixins (UniqueFieldsMixin and NestedCreateMixin or NestedUpdateMixin) you should put UniqueFieldsMixin ahead.
For example:
class ChildSerializer(UniqueFieldsMixin, NestedUpdateMixin, serializers.ModelSerializer):
Authors
2014-2020, beda.software
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~