码迷,mamicode.com
首页 > 其他好文 > 详细

Django REST framework 中的序列化器

时间:2018-07-17 16:29:54      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:register   date   include   def   site   package   lower   访问   view   

在此之前定义一个序列化工具:
 
 
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
 
View Code

 

 
成功创建对象
>>> 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)

 

 
 

Django REST framework 中的序列化器

标签:register   date   include   def   site   package   lower   访问   view   

原文地址:https://www.cnblogs.com/cerofang/p/9323140.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!