Django REST framework 中的序列化器 - Go语言中文社区

Django REST framework 中的序列化器


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

 

 
 

转载于:https://www.cnblogs.com/cerofang/p/9323140.html

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_34275734/article/details/93923038
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-14 00:40:24
  • 阅读 ( 722 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢