在此之前定义一个序列化工具:
views中的的代码
from rest_framework.viewsets import ModelViewSet from .models import BookInfo from .serializers import BookInfoSerializers class BookInfoViewSet(ModelViewSet): queryset = BookInfo.objects.all() # 取序列化模型 serializer_class = BookInfoSerializers # 指定序列化的类
定制url
from django.conf.urls import url, include from . import views from rest_framework.routers import DefaultRouter router = DefaultRouter() router.register(r"books", views.BookInfoViewSet) urlpatterns = [ url(r‘^index/$‘, views.index), ] urlpatterns += router.urls
访问路径配置
http://127.0.0.1:8000/app001/books/
定制普通的序列化类
已有的model数据类型如下所示:
class BookInfo(models.Model): btitle = models.CharField(max_length=20, verbose_name=‘名称‘) bpub_date = models.DateField(verbose_name=‘发布日期‘) bread = models.IntegerField(default=0, verbose_name=‘阅读量‘) bcomment = models.IntegerField(default=0, verbose_name=‘评论量‘) is_delete = models.BooleanField(default=False, verbose_name=‘逻辑删除‘) class Meta: db_table = ‘tb_books‘ # 指明数据库表名 verbose_name = ‘图书‘ # 在admin站点中显示的名称 verbose_name_plural = verbose_name # 显示的复数名称 def __str__(self): return self.btitle
继承serializers.Serializer的序列化器:
# 为以上的model定制一个序列化器
from rest_framework import serializers class BookInfoSerializers(serializers.Serializer): """ 图书列表序列化器""" id = serializers.IntegerField(label="ID", read_only=True) btitle = serializers.CharField(label="名称", max_length=20) bpub_date = serializers.DateField(label=‘发布日期‘, required=False) bread = serializers.IntegerField(label=‘阅读量‘, required=False) bcomment = serializers.IntegerField(label=‘评论量‘, required=False) is_delete = serializers.BooleanField(label=‘逻辑删除‘, required=False)
演示效果(python manages.py shell的环境下运行):
# 查询图书的的对象 from app001.models import BookInfo book = BookInfo.objects.all()[0] # 构造序列化器 from app001.serializers import BookInfoSerializers serializer = BookInfoSerializers(book) # 获取序列化之后的属性 print(serializer.data) # 打印效果: """ {‘id‘: 1, ‘bpub_date‘: ‘1980-05-01‘, ‘btitle‘: ‘射雕英雄传‘, ‘is_delete‘: False, ‘bcomment‘: 34, ‘bread‘: 12} """
model类
class HeroInfo(models.Model): GENDER_CHOICES = ( (0, ‘male‘), (1, ‘female‘) ) hname = models.CharField(max_length=20, verbose_name=‘名称‘) hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name=‘性别‘) hcomment = models.CharField(max_length=200, null=True, verbose_name=‘描述信息‘) hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name=‘图书‘) # 外键 is_delete = models.BooleanField(default=False, verbose_name=‘逻辑删除‘) class Meta: db_table = ‘tb_heros‘ verbose_name = ‘英雄‘ verbose_name_plural = verbose_name def __str__(self): return self.hname
序列化器
from rest_framework import serializers class HeroInfoSerializers(serializers.Serializer): """英雄数据序列化器""" GENDER_CHOICES = ( (0, ‘male‘), (1, ‘female‘) ) # hname = models.CharField(max_length=20, verbose_name=‘名称‘) id = serializers.IntegerField(label=‘ID‘, read_only=True) # hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name=‘性别‘) hgender = serializers.ChoiceField(choices=GENDER_CHOICES, label=‘性别‘, required=False) # hcomment = models.CharField(max_length=200, null=True, verbose_name=‘描述信息‘) hcomment = serializers.CharField(label=‘描述信息‘, max_length=200, required=False, allow_null=True) # hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name=‘图书‘) # 外键 hbook = serializers.PrimaryKeyRelatedField(label=‘图书‘, read_only=True) # is_delete = models.BooleanField(default=False, verbose_name=‘逻辑删除‘)
交互界面输出
# 查询英雄的对象
from app001.models import HeroInfo hero = HeroInfo.objects.all()[0] from app001.serializers import HeroInfoSerializers hs = HeroInfoSerializers(hero) print(hs.data)
"""
{‘hgender‘: 1, ‘id‘: 1, ‘hcomment‘: ‘降龙掌‘, ‘hbook‘: ‘射雕英雄传‘}
{‘hgender‘: 1, ‘id‘: 1, ‘hcomment‘: ‘降龙掌‘, ‘hbook‘: 1}
"""
此字段将被序列化为关联对象的主键。
(hbook = serializers.PrimaryKeyRelatedField(label=‘图书‘, read_only=True)
hbook = serializers.PrimaryKeyRelatedField(label=‘图书‘,queryset=BookInfo.objects.all()))
print(hs.data)
"""
{‘hgender‘: 1, ‘id‘: 1, ‘hcomment‘: ‘降龙掌‘, ‘hbook‘: 1}
"""
(hbook = serializers.StringRelatedField(label=‘图书‘))
print(hs.data)
"""
{‘hgender‘: 1, ‘id‘: 1, ‘hcomment‘: ‘降龙掌‘, ‘hbook‘: ‘射雕英雄传‘}
"""
( hbook = serializers.SlugRelatedField(label=‘图书‘, read_only=True, slug_field=‘bpub_date‘)
)
{‘hbook‘: datetime.date(1980, 5, 1), ‘hcomment‘: ‘降龙掌‘, ‘hgender‘: 1, ‘id‘: 1}
( hbook = BookInfoSerializers()
)
{‘hgender‘: 1, ‘hcomment‘: ‘降龙掌‘, ‘id‘: 1, ‘hbook‘: OrderedDict([(‘id‘, 1), (‘btitle‘, ‘射雕英雄传‘), (‘bpub_date‘, ‘1980-05-01‘), (‘bread‘, 12), (‘bcomment‘, 34), (‘is_delete‘, False)])}
( hbook = BookRelateField(read_only="True"))
{‘hcomment‘: ‘降龙掌‘, ‘hbook‘: ‘Book: 1 射雕英雄传‘, ‘id‘: 1, ‘hgender‘: 1}
( heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增
)
测试命令
from app001.models import BookInfo book = BookInfo.objects.all()[0] # 构造序列化器 from app001.serializers import BookInfoSerializers bs = BookInfoSerializers(book) # 获取序列化之后的属性 print(bs.data)
{‘bread‘: 12, ‘is_delete‘: False, ‘bpub_date‘: ‘1980-05-01‘, ‘heroinfo_set‘: [1, 2, 3, 4, 5], ‘btitle‘: ‘射雕英雄传‘, ‘id‘: 1, ‘bcomment‘: 34}
from app001.serializers import BookInfoSerializers data = {‘bpub_date‘: 123} serializer = BookInfoSerializers(data=data) serializer.is_valid() serializer.errors serializer.validated_data
from app001.serializers import BookInfoSerializers data = {‘bpub_date‘: "1993-12-27", ‘btitle‘: ‘python‘} serializer = BookInfoSerializers(data=data) serializer.is_valid() serializer.errors serializer.validated_data
"""
OrderedDict([(‘btitle‘, ‘python‘), (‘bpub_date‘, datetime.date(1993, 12, 27))])
"""
验证失败报404异常
serializer.is_valid(raise_exception=True)
from rest_framework import serializers class BookInfoSerializers(serializers.Serializer): """ 图书列表序列化器""" id = serializers.IntegerField(label="ID", read_only=True) btitle = serializers.CharField(label="名称", max_length=20) bpub_date = serializers.DateField(label=‘发布日期‘, required=False) bread = serializers.IntegerField(label=‘阅读量‘, required=False) bcomment = serializers.IntegerField(label=‘评论量‘, required=False) is_delete = serializers.BooleanField(label=‘逻辑删除‘, required=False) heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增 def validate_btitle(self, value): if ‘django‘ not in value.lower(): raise serializers.ValidationError("图书不是关于Django的") return value
from app001.serializers import BookInfoSerializers
data = {‘bpub_date‘: "1993-12-27", ‘btitle‘: ‘python_django‘}
serializer = BookInfoSerializers(data=data)
serializer.is_valid()
serializer.errors
serializer.validated_data
"""
OrderedDict([(‘btitle‘, ‘python_django‘), (‘bpub_date‘, datetime.date(1993, 12, 27))])
"""
在序列化器中定义一个validate()在这个方法中定义的字段会在最后被验证;
from rest_framework import serializers def about_django(value): if ‘django‘ not in value.lower(): raise serializers.ValidationError("about_django中抛出图书不是关于Django的") class BookInfoSerializers(serializers.Serializer): """ 图书列表序列化器""" id = serializers.IntegerField(label="ID", read_only=True) btitle = serializers.CharField(label="名称", max_length=20,validators=[about_django]) bpub_date = serializers.DateField(label=‘发布日期‘, required=False) bread = serializers.IntegerField(label=‘阅读量‘, required=False) bcomment = serializers.IntegerField(label=‘评论量‘, required=False) is_delete = serializers.BooleanField(label=‘逻辑删除‘, required=False) heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增 def validate(self, attrs): bread = attrs[‘bread‘] bcomment = attrs[‘bcomment‘] if bread < bcomment: raise serializers.ValidationError(‘阅读量小于评论量‘) return attrs
>>> from app001.serializers import BookInfoSerializers >>> data = {‘bcomment‘: 34, ‘bread‘: 12,‘bpub_date‘: "1993-12-27", ‘btitle‘: ‘python_django‘} >>> serializer = BookInfoSerializers(data=data) >>> serializer.is_valid() False >>> serializer.errors {‘non_field_errors‘: [ErrorDetail(string=‘阅读量小于评论量‘, code=‘invalid‘)]} >>> serializer.validated_data {}
抛出异常:
>>> from app001.serializers import BookInfoSerializers >>> data = {‘bcomment‘: 14, ‘bread‘: 12,‘bpub_date‘: "1993-12-27", ‘btitle‘: ‘ptython‘} >>> serializer = BookInfoSerializers(data=data) >>> serializer.is_valid() False >>> serializer.errors {‘btitle‘: [ErrorDetail(string=‘about_django中抛出图书不是关于Django的‘, code=‘invalid‘)]} >>> serializer.validated_data {} >>>
在序列化器类的内部定义一个方法,来验证字段的属性(注意定义的函数的结构);
from rest_framework import serializers class BookInfoSerializers(serializers.Serializer): """ 图书列表序列化器""" id = serializers.IntegerField(label="ID", read_only=True) btitle = serializers.CharField(label="名称", max_length=20,validators=[about_django]) bpub_date = serializers.DateField(label=‘发布日期‘, required=False) bread = serializers.IntegerField(label=‘阅读量‘, required=False) bcomment = serializers.IntegerField(label=‘评论量‘, required=False) is_delete = serializers.BooleanField(label=‘逻辑删除‘, required=False) heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增 def validate_btitle(self, value): if ‘django‘ not in value.lower(): raise serializers.ValidationError("图书不是关于Django的") return value
验证成功:
>>> from app001.serializers import BookInfoSerializers >>> data = {‘bcomment‘: 10, ‘bread‘: 12,‘bpub_date‘: "1993-12-27", ‘btitle‘: ‘python_django‘} >>> serializer = BookInfoSerializers(data=data) >>> serializer.is_valid() True >>> serializer.errors {} >>> serializer.validated_data OrderedDict([(‘btitle‘, ‘python_django‘), (‘bpub_date‘, datetime.date(1993, 12, 27)), (‘bread‘, 12), (‘bcomment‘, 10)]) >>>
验证失败:
>>> from app001.serializers import BookInfoSerializers >>> data = {‘bcomment‘: 10, ‘bread‘: 12,‘bpub_date‘: "1993-12-27", ‘btitle‘: ‘ptython‘} >>> serializer = BookInfoSerializers(data=data) >>> serializer.is_valid() False >>> serializer.errors {‘btitle‘: [ErrorDetail(string=‘图书不是关于Django的‘, code=‘invalid‘)]} >>> serializer.validated_data {}
在序列化器的外部定义一个方法,将该方法加入到字段中作为字段的验证方法
from rest_framework import serializers def about_django(value): if ‘django‘ not in value.lower(): raise serializers.ValidationError("图书不是关于Django的") class BookInfoSerializers(serializers.Serializer): """ 图书列表序列化器""" id = serializers.IntegerField(label="ID", read_only=True) btitle = serializers.CharField(label="名称", max_length=20,validators=[about_django]) bpub_date = serializers.DateField(label=‘发布日期‘, required=False) bread = serializers.IntegerField(label=‘阅读量‘, required=False) bcomment = serializers.IntegerField(label=‘评论量‘, required=False) is_delete = serializers.BooleanField(label=‘逻辑删除‘, required=False) heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增 def validate_btitle(self, value): if ‘django‘ not in value.lower(): raise serializers.ValidationError("图书不是关于Django的") return value def validate(self, attrs): bread = attrs[‘bread‘] bcomment = attrs[‘bcomment‘] if bread < bcomment: raise serializers.ValidationError(‘阅读量小于评论量‘) return attrs
返回成功:
>>> from app001.serializers import BookInfoSerializers >>> data = {‘bcomment‘: 10, ‘bread‘: 12,‘bpub_date‘: "1993-12-27", ‘btitle‘: ‘ptython_django‘} >>> serializer = BookInfoSerializers(data=data) >>> serializer.is_valid() True >>> serializer.errors {} >>> serializer.validated_data OrderedDict([(‘btitle‘, ‘ptython_django‘), (‘bpub_date‘, datetime.date(1993, 12, 27)), (‘bread‘, 12), (‘bcomment‘, 10)])
返回失败:
>>> from app001.serializers import BookInfoSerializers >>> data = {‘bcomment‘: 10, ‘bread‘: 12,‘bpub_date‘: "1993-12-27", ‘btitle‘: ‘ptython‘} >>> serializer = BookInfoSerializers(data=data) >>> serializer.is_valid() False >>> serializer.errors {‘btitle‘: [ErrorDetail(string=‘about_django中抛出图书不是关于Django的‘, code=‘invalid‘)]} >>> serializer.validated_data {}
验证顺序:
验证顺序:
1,model字段本身;
2,字段中定义的validators;
3,序列化器中定义的对字段的验证方法validate_字段名;
4, 序列话器中validate的方法。
单字段唯一;
from rest_framework.validators import UniqueValidator slug = SlugField( max_length=100, validators=[UniqueValidator(queryset=BlogPost.objects.all())] )
联合唯一;
from rest_framework.validators import UniqueTogetherValidator class ExampleSerializer(serializers.Serializer): # ... class Meta: validators = [ UniqueTogetherValidator( queryset=ToDoItem.objects.all(), fields=(‘list‘, ‘position‘) ) ]
序列化后的数据保存
验证未通过程序包报错:
>>> from app001.serializers import BookInfoSerializers >>> data = {‘btitle‘: ‘封神演义‘} >>> serializer = BookInfoSerializers(data=data) >>> serializer.is_valid() False >>> serializer.save() Traceback (most recent call last): File "<console>", line 1, in <module> File "/home/python/.virtualenvs/djf/lib/python3.5/site-packages/rest_framework/serializers.py", line 184, in save ‘You cannot call `.save()` on a serializer with invalid data.‘ AssertionError: You cannot call `.save()` on a serializer with invalid data.
验证通过并保存
>>> from app001.serializers import BookInfoSerializers >>> data = {‘bcomment‘: 10, ‘bread‘: 12,‘bpub_date‘: "1993-12-27", ‘btitle‘: ‘ptython_django‘} >>> serializer = BookInfoSerializers(data=data) >>> serializer.is_valid() True >>> serializer.save() <BookInfo: ptython_django>
序列化器的定义
from rest_framework import serializers def about_django(value): if ‘django‘ not in value.lower(): raise serializers.ValidationError("about_django中抛出图书不是关于Django的") class BookInfoSerializers(serializers.Serializer): """ 图书列表序列化器""" id = serializers.IntegerField(label="ID", read_only=True) btitle = serializers.CharField(label="名称", max_length=20, validators=[about_django]) bpub_date = serializers.DateField(label=‘发布日期‘, required=False) bread = serializers.IntegerField(label=‘阅读量‘, required=False) bcomment = serializers.IntegerField(label=‘评论量‘, required=False) is_delete = serializers.BooleanField(label=‘逻辑删除‘, required=False) heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增 def validate_btitle(self, value): if ‘django‘ not in value.lower(): raise serializers.ValidationError("图书不是关于Django的") return value def create(self, validated_data): """新建""" return BookInfo.objects.create(**validated_data) def update(self, instance, validated_data): """更新,instance为要更新的对象实例""" instance.btitle = validated_data.get(‘btitle‘, instance.btitle) instance.bpub_date = validated_data.get(‘bpub_date‘, instance.bpub_date) instance.bread = validated_data.get(‘bread‘, instance.bread) instance.bcomment = validated_data.get(‘bcomment‘, instance.bcomment) instance.save() return instance
成功创建对象
>>> from app001.serializers import BookInfoSerializers >>> # from app001.models import BookInfo >>> # book = BookInfo.objects.filter(btitle="ptython_django")[0] >>> book = BookInfo.objects.get(id=10) >>> data = {‘bcomment‘: 10, ‘bread‘: 12,‘bpub_date‘: "1994-12-27", ‘btitle‘: ‘ptython_django‘} >>> # data = {‘bpub_date‘: "1994-12-27",‘bcomment‘: 10, ‘bread‘: 12,} >>> serializer = BookInfoSerializers(book, data=data) >>> serializer.is_valid() True >>> serializer.save() <BookInfo: ptython_django> >>> book.btitle ‘ptython_django‘ >>>
成功修改对象传入对象中的属性;
>>> from app001.serializers import BookInfoSerializers >>> from app001.models import BookInfo >>> book = BookInfo.objects.filter(btitle="ptython_django")[0] >>> data = {‘bcomment‘: 10, ‘bread‘: 12,‘bpub_date‘: "1995-12-27", ‘btitle‘: ‘ptython_django‘} >>> serializer = BookInfoSerializers(book, data=data) >>> serializer.is_valid() True >>> serializer.save() <BookInfo: ptython_django> >>> book.btitle ‘ptython_django‘ >>> book.bpub_date datetime.date(1995, 12, 27)
修改通过书名取到的的对象的值;
>>> from app001.serializers import BookInfoSerializers >>> from app001.models import BookInfo >>> book = BookInfo.objects.filter(btitle="ptython_django")[0] >>> data = {‘bpub_date‘: "1996-12-27", ‘btitle‘: ‘ptython_django‘} >>> serializer = BookInfoSerializers(book, data=data) >>> serializer.is_valid() True >>> serializer.save() <BookInfo: ptython_django> >>> book.btitle ‘ptython_django‘ >>> book.bpub_date datetime.date(1996, 12, 27)
原文地址:https://www.cnblogs.com/cerofang/p/9323140.html