zoukankan      html  css  js  c++  java
  • 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)
     
     
  • 相关阅读:
    IOS 改变UISearchBar的背景色
    电话正则表达式
    理解Callable 和 Spring DeferredResult(翻译)
    Java设计模式——观察者模式(事件监听)
    SpringMVC注解@initbinder解决类型转换问题
    内部系统间调用client包的封装方法
    Java中Comparable和Comparator实现对象比较
    linux上FTP服务器搭建
    百度地图——判断用户是否在配送范围内解决方案
    nodejs之express的使用
  • 原文地址:https://www.cnblogs.com/cerofang/p/9323140.html
Copyright © 2011-2022 走看看