zoukankan      html  css  js  c++  java
  • Serializer序列器

    定义Serializer

    1. 定义方法

    Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。

    例如,我们已有了一个数据库模型类BookInfo

    class BookInfo(models.Model):
        btitle = models.CharField(max_length=20, verbose_name='名称')
        bpub_date = models.DateField(verbose_name='发布日期', null=True)
        bread = models.IntegerField(default=0, verbose_name='阅读量')
        bcomment = models.IntegerField(default=0, verbose_name='评论量')
        image = models.ImageField(upload_to='booktest', verbose_name='图片', null=True)

    我们想为这个模型类提供一个序列化器,可以定义如下:

    class BookInfoSerializer(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)
        image = serializers.ImageField(label='图片', required=False)

    注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。

    2. 字段与选项

    常用字段类型

    image

    image

    image

    image

    read_only:True表示不允许用户自己上传,只能用于api的输出。如果某个字段设置了read_only=True,那么就不需要进行数据验证,只会在返回时,将这个字段序列化后返回


    write_only:与read_only对应;就是用户post过来的数据,后台服务器处理后不会再经过序列化后返回给客户端;最常见的就是我们在使用手机注册的验证码和填写的密码。

    3. 创建Serializer对象

    Serializer的构造方法为:

    Serializer(instance=None, data=empty, **kwarg)

    说明:

    1)用于序列化时,将模型类对象传入instance参数

    2)用于反序列化时,将要被反序列化的数据传入data参数

    3)除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如

    serializer = AccountSerializer(account, context={'request': request})

    通过context参数附加的数据,可以通过Serializer对象的context属性获取。

     

    Serializer使用

    我们定义一个测试视图来使用序列化器,如下:

    views

    def test(request):
        return HttpResponse('ok')

    urls

    urlpatterns = [
        url(r'^test/$', views.test)
    ]
    

    1. 基本使用

    def test(request):
        book = BookInfo.objects.get(id=5)  # 先查询出一个图书对象
        serializer = BookInfoSerializer(book)  # 构建序列化
        print(serializer.data)  # 获取序列化数据  {'image': None, 'btitle': '西游记', 'id': 5, 'bread': 10, 'bcomment': 10, 'bpub_date': '1988-01-01'}
    
        return HttpResponse('ok')

    如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明

    def test(request):
        book = BookInfo.objects.all()  # 先查询出一个图书对象
        serializer = BookInfoSerializer(book, many=True)  # 构建序列化
        print(serializer.data)  # 获取序列化数据  {'image': None, 'btitle': '西游记', 'id': 5, 'bread': 10, 'bcomment': 10, 'bpub_date': '1988-01-01'}
    
        return HttpResponse('ok')

    2. 关联对象嵌套序列化

    如果需要序列化的数据中包含有其他关联对象,则对关联对象数据的序列化需要指明。

    例如,在定义英雄数据的序列化器时,外键hbook(即所属的图书)字段如何序列化?

    我们先定义HeroInfoSerialzier除外键字段外的其他部分

    对于关联字段,可以采用以下几种方式:

    1. PrimaryKeyRelatedField

    此字段将被序列化为关联对象的主键。

    hbook = serializers.PrimaryKeyRelatedField(label='图书', read_only=True)
    或
    hbook = serializers.PrimaryKeyRelatedField(label='图书', queryset=BookInfo.objects.all())

    指明字段时需要包含read_only=True或者queryset参数:

    • 包含read_only=True参数时,该字段将不能用作反序列化使用
    • 包含queryset参数时,将被用作反序列化时参数校验使用

    使用效果:

    def test(request):
        hero = HeroInfo.objects.get(id=10)  # 查询一个英雄对象
        serializer = HeroInfoSerializer(hero) # 构建序列化
        print(serializer.data)  # 返回序列化内容 {'id': 10, 'hcomment': '独孤九剑', 'hname': '令狐冲', 'hbook': 3, 'hgender': 1}
        return HttpResponse('ok')

    报错:说明id不存在

    image

    2. StringRelatedField

    此字段将被序列化为关联对象的字符串表示方式(即__str__方法的返回值)

    hbook = serializers.StringRelatedField(label='图书')
    def test(request):
        hero = HeroInfo.objects.get(id=11)  # 查询一个英雄对象
        serializer = HeroInfoSerializer(hero) # 构建序列化
        print(serializer.data)  # 返回序列化内容 {'hgender': 0, 'hbook': '笑傲江湖', 'id': 11, 'hname': '任盈盈', 'hcomment': '弹琴'}
        return HttpResponse('ok')
    3. 使用关联对象的序列化器
    hbook = BookInfoSerializer()
    
    
    def test(request):
        hero = HeroInfo.objects.get(id=11)  # 查询一个英雄对象
        serializer = HeroInfoSerializer(hero) # 构建序列化
        print(serializer.data)  # 返回序列化内容 {'hgender': 0, 'hbook': OrderedDict([('id', 3), ('btitle', '笑傲江湖'), ('bpub_date', '1995-12-24'), ('bread', 20), ('bcomment', 80), ('image', None)]), 'hcomment': '弹琴', 'id': 11, 'hname': '任盈盈'}
        return HttpResponse('ok')
    4. HyperlinkedRelatedField

    此字段将被序列化为获取关联对象数据的接口链接

    hbook = serializers.HyperlinkedRelatedField(label='图书', read_only=True, view_name='books-detail')

    必须指明view_name参数,以便DRF根据视图名称寻找路由,进而拼接成完整URL。

    {'id': 6, 'hname': '乔峰', 'hgender': 1, 'hcomment': '降龙十八掌', 'hbook': 'http://127.0.0.1:8000/books/2/'}
    5. SlugRelatedField

    此字段将被序列化为关联对象的指定字段数据

    slug_field指明使用关联对象的哪个字段

    hbook = serializers.SlugRelatedField(label='图书', read_only=True, slug_field='bpub_date')
    def test(request):
        hero = HeroInfo.objects.get(id=11)  # 查询一个英雄对象
        serializer = HeroInfoSerializer(hero) # 构建序列化
        print(serializer.data)  # 返回序列化内容 {'id': 11, 'hgender': 0, 'hcomment': '弹琴', 'hname': '任盈盈', 'hbook': datetime.date(1995, 12, 24)}
    
        return HttpResponse('ok')
    6. 重写to_representation方法

    序列化器的每个字段实际都是由该字段类型的to_representation方法决定格式的,可以通过重写该方法来决定格式。

    注意,to_representations方法不仅局限在控制关联对象格式上,适用于各个序列化器字段类型。

    自定义一个新的关联字段:

    class BookRelateField(serializers.RelatedField):
        """自定义用于处理图书的字段"""
        def to_representation(self, value):
            return 'Book: %d %s' % (value.id, value.btitle)
    hbook = BookRelateField(read_only=True)
    def test(request):
        hero = HeroInfo.objects.get(id=11)  # 查询一个英雄对象
        serializer = HeroInfoSerializer(hero) # 构建序列化
        print(serializer.data)  # 返回序列化内容 {'hbook': 'Book: 3 笑傲江湖', 'id': 11, 'hcomment': '弹琴', 'hname': '任盈盈', 'hgender': 0}
        return HttpResponse('ok')

    many参数

    如果关联的对象数据不是只有一个,而是包含多个数据,如想序列化图书BookInfo数据,每个BookInfo对象关联的英雄HeroInfo对象可能有多个,此时关联字段类型的指明仍可使用上述几种方式,只是在声明关联字段时,多补充一个many=True参数即可。

    此处仅拿PrimaryKeyRelatedField类型来举例,其他相同。

    在BookInfoSerializer中添加关联字段:

    class BookInfoSerializer(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)
        image = serializers.ImageField(label='图片', required=False)
        heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True)  # 新增

    使用效果:

    def test(request):
        book = BookInfo.objects.get(id=3)  # 查询一个英雄对象
        serializer = BookInfoSerializer(book) # 构建序列化
        print(serializer.data)  # 返回序列化内容 {'image': None, 'id': 3, 'bpub_date': '1995-12-24', 'bcomment': 80, 'bread': 20, 'heroinfo_set': [10, 11, 12, 13], 'btitle': '笑傲江湖'}
    
        return HttpResponse('ok')
  • 相关阅读:
    metal的gpu query
    体积雾 global fog unity 及改进
    hdr rt format对颜色的影响
    unity deferred lighting
    unity linear space时 photoshop blend的正确设置
    unity linear work flow
    一些数据 bandwidth之类
    deferred rendering with msaa
    unity 显示mipmaplevel
    【转】在C#中使用SendMessage
  • 原文地址:https://www.cnblogs.com/py-web/p/10937141.html
Copyright © 2011-2022 走看看