zoukankan      html  css  js  c++  java
  • Django_rest_framework(DRF)

    1. 概述

    DRF:Django REST framework是一个建立在Django基础之上的Web 应用开发框架,可以快速的开发REST API接口应用。

    在REST framework中,提供了序列化器Serialzier的定义,可以帮助我们简化序列化与反序列化的过程,不仅如此,还提供丰富的类视图、扩展类、视图集来简化视图的编写工作。REST framework还提供了认证、权限、限流、过滤、分页、接口文档等功能支持。REST framework提供了一个API 的Web可视化界面来方便查看测试接口。

    特点

    • 提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;

    • 提供了丰富的类视图、Mixin扩展类,简化视图的编写;

    • 丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要;

    • 多种身份认证和权限认证方式的支持;[jwt]

    • 内置了限流系统;

    • 直观的 API web 界面;

    • 可扩展性,插件丰富

    安装

    pip install djangorestframework

    使用

    在settings.py里的INSTALLED_APPS中添加'rest_framework'

    INSTALLED_APPS = [
        ...
        'rest_framework',    
    ]

    接下来就可以使用DRF提供的功能进行api接口开发了。在项目中如果使用rest_framework框架实现API接口,主要有以下三个步骤:

    • 将请求的数据(如JSON格式)转换为模型类对象

    • 操作数据库

    • 将模型类对象转换为响应的数据(如JSON格式)

    2 序列化器(Serializer)

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

    作用

    1. 序列化:把模型对象转换成字典(经过response以后变成json字符串)
    2. 反序列化:把字典转成模型(把客户端发送过来的数据,经过request以后变成字典)
    3. 完成数据校验功能

    举例说明

    在一个app里操作,假设已有一个数据库模型类student。

    model.py

    from django.db import models
    
    # Create your models here.
    class Student(models.Model):
        # 模型字段
        name = models.CharField(max_length=100,verbose_name="姓名",help_text="提示文本:账号不能为空!")
        sex = models.BooleanField(default=True,verbose_name="性别")
        age = models.IntegerField(verbose_name="年龄")
        class_null = models.CharField(max_length=5,verbose_name="班级编号")
        description = models.TextField(verbose_name="个性签名")
    
        class Meta:
            db_table="tb_student"
            verbose_name = "学生"
            verbose_name_plural = verbose_name

    2.1 定义序列化器

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

    在app里创建一个serializers.py,内容如下

    from rest_framework import serializers
    
    # 声明序列化器,所有的序列化器都要直接或者间接继承于 Serializer
    # 其中,ModelSerializer是Serializer的子类,ModelSerializer在Serializer的基础上进行了代码简化
    class StudentSerializer(serializers.Serializer):
        """学生信息序列化器"""
        # 1. 需要进行数据转换的字段
        id = serializers.IntegerField()
        name = serializers.CharField()
        age = serializers.IntegerField()
        sex = serializers.BooleanField()
        description = serializers.CharField()
    
        # 2. 如果序列化器集成的是ModelSerializer,则需要声明调用的模型信息
    
        # 3. 验证代码
    
        # 4. 编写添加和更新模型的代码

    2.2 序列化器的使用

    序列化器的使用分两个阶段:

    1. 在客户端请求时,使用序列化器可以完成对数据的反序列化。(写入数据则进行验证)

    2. 在服务器响应时,使用序列化器可以完成对数据的序列化。

    必要步骤:创建Serializer对象

    定义好StudentSerializer类后,就可以创建StudentSerializer对象了:

      views.py中导入定义好的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属性获取

    1. 使用序列化器的时候一定要注意,序列化器声明了以后,不会自动执行,需要我们在视图中进行调用才可以。

    2. 序列化器无法直接接收数据,需要我们在视图中创建序列化器对象时把使用的数据传递过来

    3. 序列化器的字段声明类似于我们前面使用过的表单系统

    4. 开发restful api时,序列化器会帮我们把模型数据转换成字典

    5. drf提供的视图会帮我们把字典转换成json,或者把客户端发送过来的数据转换字典

     

     

     2.2.1 序列化

    1. 先查询出一个学生对象
      from students.models import Student
      
      student = Student.objects.get(id=3)
    2. 构造序列化器对象
      from .serializers import StudentSerializer
      
      serializer = StudentSerializer(instance=student)
    3. 获取序列化数据
      serializer.data
      # {'id': 4, 'name': '小张', 'age': 18, 'sex': True, 'description': '猴赛雷'}

    完整视图代码:

    views.py

    from django.views import View
    from students.models import Student
    from .serializers import StudentSerializer
    from django.http.response import JsonResponse
    class StudentView(View): """使用序列化器序列化转换单个模型数据""" def get(self,request,pk): # 获取数据 student = Student.objects.get(pk=pk) # 数据转换[序列化过程] serializer = StudentSerializer(instance=student) print(serializer.data) # 响应数据 return JsonResponse(serializer.data)

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

        """使用序列化器序列化转换多个模型数据"""
        def get(self,request):
            # 获取数据
            student_list = Student.objects.all()
    
            # 转换数据[序列化过程]
            # 如果转换多个模型对象数据,则需要加上many=True
            serializer = StudentSerializer(instance=student_list,many=True)
            print( serializer.data ) # 序列化器转换后的数据
    
            # 响应数据给客户端
            # 返回的json数据,如果是列表,则需要声明safe=False
            return JsonResponse(serializer.data,safe=False)
        
        
        # 访问结果:
        # [OrderedDict([('id', 1), ('name', 'xiaoming'), ('age', 20), ('sex', True), ('description', '测试')]), OrderedDict([('id', 2), ('name', 'xiaohui'), ('age', 22), ('sex', True), ('description', '后面来的测试')]), OrderedDict([('id', 4), ('name', '小张'), ('age', 18), ('sex', True), ('description', '猴赛雷')])]

    2.2.2 反序列化

    2.2.2.1 数据验证

    注意

    • 使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象
    • 在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False
    • 验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。
    • 验证成功,可以通过序列化器对象的validated_data属性获取数据
    • 在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为,如
      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)

    通过构造序列化器对象,并将要反序列化的数据传递给data构造参数,进而进行验证

    from booktest.serializers import BookInfoSerializer
    data = {'bpub_date': 123}
    serializer = BookInfoSerializer(data=data)
    serializer.is_valid()  # 返回False
    serializer.errors
    # {'btitle': [ErrorDetail(string='This field is required.', code='required')], 'bpub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].', code='invalid')]}
    serializer.validated_data  # {}
    
    data = {'btitle': 'python'}
    serializer = BookInfoSerializer(data=data)
    serializer.is_valid()  # True
    serializer.errors  # {}
    serializer.validated_data  #  OrderedDict([('btitle', 'python')])

    is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。

    # Return a 400 response if the data was invalid.
    serializer.is_valid(raise_exception=True)

    如果觉得这些还不够,需要再补充定义验证行为,可以使用以下三种方法:

    1) validate_字段名

    <field_name>字段进行验证,如

    class BookInfoSerializer(serializers.Serializer):
        """图书数据序列化器"""
        ...
    
        def validate_btitle(self, value):
            if 'django' not in value.lower():
                raise serializers.ValidationError("图书不是关于Django的")
            return value

    测试:

    from booktest.serializers import BookInfoSerializer
    data = {'btitle': 'python'}
    serializer = BookInfoSerializer(data=data)
    serializer.is_valid()  # False   
    serializer.errors
    #  {'btitle': [ErrorDetail(string='图书不是关于Django的', code='invalid')]}
    2) validate

    在序列化器中需要同时对多个字段进行比较验证时,可以定义validate方法来验证,如

    class BookInfoSerializer(serializers.Serializer):
        """图书数据序列化器"""
        ...
    
        def validate(self, attrs):
            bread = attrs['bread']
            bcomment = attrs['bcomment']
            if bread < bcomment:
                raise serializers.ValidationError('阅读量小于评论量')
            return attrs

    测试:

    from booktest.serializers import BookInfoSerializer
    data = {'btitle': 'about django', 'bread': 10, 'bcomment': 20}
    s = BookInfoSerializer(data=data)
    s.is_valid()  # False
    s.errors
    #  {'non_field_errors': [ErrorDetail(string='阅读量小于评论量', code='invalid')]}
    3) validators

    在字段中添加validators选项参数,也可以补充验证行为,如

    def about_django(value):
        if 'django' not in value.lower():
            raise serializers.ValidationError("图书不是关于Django的")
    
    class BookInfoSerializer(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)
        image = serializers.ImageField(label='图片', required=False)

    测试:

    from booktest.serializers import BookInfoSerializer
    data = {'btitle': 'python'}
    serializer = BookInfoSerializer(data=data)
    serializer.is_valid()  # False   
    serializer.errors
    #  {'btitle': [ErrorDetail(string='图书不是关于Django的', code='invalid')]}
    2.2.2.2 反序列化-保存

    前面的验证数据成功后,我们可以使用序列化器来完成数据反序列化的过程.这个过程可以把数据转成模型类对象.

    可以通过实现create()和update()两个方法来实现。

    class BookInfoSerializer(serializers.Serializer):
        """图书数据序列化器"""
        ...
    
        def create(self, validated_data):
            """新建"""
            return BookInfo(**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)
            return instance

    如果需要在返回数据对象的时候,也将数据保存到数据库中,则可以进行如下修改

    class BookInfoSerializer(serializers.Serializer):
        """图书数据序列化器"""
        ...
    
        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

    实现了上述两个方法后,在反序列化数据的时候,就可以通过save()方法返回一个数据对象实例了

    book = serializer.save()

    如果创建序列化器对象的时候,没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,则调用save()方法的时候,update()被调用。

    from db.serializers import BookInfoSerializer
    data = {'btitle': '封神演义'}
    serializer = BookInfoSerializer(data=data)
    serializer.is_valid()  # True
    serializer.save()  # <BookInfo: 封神演义>
    
    from db.models import BookInfo
    book = BookInfo.objects.get(id=2)
    data = {'btitle': '倚天剑'}
    serializer = BookInfoSerializer(book, data=data)
    serializer.is_valid()  # True
    serializer.save()  # <BookInfo: 倚天剑>
    book.btitle  # '倚天剑'

    注意create与updata方法需要手动定义

    2.2.2.3 附加说明

    1) 在对序列化器进行save()保存时,可以额外传递数据,这些数据可以在create()和update()中的validated_data参数获取到

    # request.user 是django中记录当前登录用户的模型对象
    serializer.save(owner=request.user)

    2)默认序列化器必须传递所有required的字段,否则会抛出验证异常。但是我们可以使用partial参数来允许部分字段更新

    # Update `comment` with partial data
    serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)

    3. 请求与相应

    4. 视图

  • 相关阅读:
    20160729noip模拟赛zld
    20160728noip模拟赛zld
    20160727noip模拟赛zld
    20160725noip模拟赛“Paodekuai” alexandrali
    20160723数据结构节alexandrali
    20160722noip模拟赛alexandrali
    洛谷 [P2594] 染色游戏
    洛谷 [P3480] KAM-Pebbles
    UVA 1378 A Funny Stone Game
    SPOJ 4060 A game with probability
  • 原文地址:https://www.cnblogs.com/yijue-lu/p/10887115.html
Copyright © 2011-2022 走看看