1.DRF环境安装与配置

DRF需要以下依赖:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
  • Python (2.7, 3.2, 3.3, 3.4, 3.5, 3.6)

  • Django (1.10, 1.11, 2.0)

DRF是以Django扩展应用的方式提供的,所以我们可以直接利用已有的Django环境而无需从新创建。(若没有Django环境,需要先创建环境安装Django)

1.1 安装DRF

前提是已经安装了django,建议安装在虚拟环境

#本次测试环境是在ubantu的18.0环境中
# mkvirtualenv drfdemo -p python3
# pip install django

pip install djangorestframework
pip install pymysql

1.1.1 创建django项目

cd ~/Desktop
django-admin startproject drfdemo
Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第1张

使用pycharm打开项目,设置虚拟环境的解析器,并修改manage.py中的后缀参数。修改虚拟环境参数

1.2 添加rest_framework应用

settings.pyINSTALLED_APPS中添加'rest_framework'。

INSTALLED_APPS = [
    ...
    'rest_framework',
]

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

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

  • 操作数据库

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

1.3 体验DRF完全简写代码的过程(暂时不需要理解)

1.3.1 创建模型操作类

from django.db import models

# Create your models here.
class Student(models.Model):
    name = models.CharField(max_length=100,verbose_name='姓名')
    sex = models.BooleanField(default=1,verbose_name='性别')
    age = models.IntegerField(verbose_name='年龄')
    class_number = models.CharField(max_length=5,verbose_name='班级签名')
    description = models.TextField(max_length=1000,verbose_name='个性签名')

    def __str__(self):
        return self.name

    class Meta:
        db_table="tb_student"
        # 一个是单数一个是复数
        verbose_name="学生"
        verbose_name_plural=verbose_name

为了方便测试,所以我们可以先创建一个数据库。

create database students charset=utf8;

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第2张

1.3.1.1数据迁移

把students子应用添加到INSTALL_APPS中

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第3张

初始化数据库连接

安装pymysql
pip install pymysql

主引用中__init__.py设置使用pymysql作为数据库驱动

import pymysql

pymysql.install_as_MySQLdb()

settings.py配置文件中设置mysql的账号密码

DATABASES = {
    # 'default': {
    #     'ENGINE': 'django.db.backends.sqlite3',
    #     'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    # },
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': "students",
        "HOST": "127.0.0.1",
        "PORT": 3306,
        "USER": "root",
        "PASSWORD":"123",
    }
}

终端下,执行数据迁移。

python manage.py makemigrations
python manage.py migrate

在测试中碰到如下问题

1.3.1.2 django 2.1.7 版本中,数据迁移无异常

1.3.1.3 安装最新的django版本 2.2.版本后会出现迁移数据报错

# 执行数据迁移 python manage.py makemigrations 报错如下:

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第4张

解决方案:

注释掉 backends/mysql/base.py中的35和36行代码。

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第5张

# 执行数据迁移发生以下错误:

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第6张

解决方法:

backends/mysql/operations.py146行里面新增一个行代码:

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第7张

1.3.2 创建序列化器

例如,在django项目中创建学生子应用。

python manage.py startapp students

在syudents应用目录中新建serializers.py用于保存该应用的序列化器。创建一个StudentModelSerializer用于序列化与反序列化。

from rest_framework import serializers
from .models import Student

# 创建序列化器类,回头会在试图中被调用
class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = "__all__"
  • model 指明该序列化器处理的数据字段从模型类BookInfo参考生成

  • fields 指明该序列化器包含模型类中的哪些字段,'all'指明包含所有字段

1.3.3 编写视图

在students应用的views.py中创建视图StudentViewSet,这是一个视图集合。

from rest_framework.viewsets import ModelViewSet
from .models import Student
from .serializers import StudentModelSerializer
# Create your views here.
class StudentViewSet(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
  • queryset 指明该视图集在查询数据时使用的查询集

  • serializer_class 指明该视图在进行序列化或反序列化时使用的序列化器

1.3.4 定义路由

在students应用的urls.py中定义路由信息。

from . import views
from rest_framework.routers import DefaultRouter

# 路由列表
urlpatterns = []

router = DefaultRouter()  # 可以处理视图的路由器
router.register('students', views.StudentViewSet)  # 向路由器中注册视图集

urlpatterns += router.urls  # 将路由器中的所以路由信息追到到django的路由列表中

最后把students子应用中的路由文件加载到总路由文件中.

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path("stu/",include("students.urls")),
]

1.3.5 运行测试

运行当前程序(与运行Django一样)

python manage.py runserver

在浏览器中输入网址127.0.0.1:8000,可以看到DRF提供的API Web浏览页面:

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第8张

1)点击链接127.0.0.1:8000/stu/students 可以访问获取所有数据的接口,呈现如下页面:

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第9张

2)在页面底下表单部分填写学生信息,可以访问添加新学生的接口,保存学生信息:

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第10张

点击POST后,返回如下页面信息:

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第11张

3)在浏览器中输入网址127.0.0.1:8000/stu/students/5/,可以访问获取单一学生信息的接口(id为5的学生),呈现如下页面:

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第12张

4)在页面底部表单中填写学生信息,可以访问修改学生的接口

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第13张

点击PUT,返回如下页面信息:

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第14张

5)点击DELETE按钮,可以访问删除学生的接口

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第15张

返回,如下页面:

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第16张

从上面我们知道,一个drf的应用大概流程为

  1. 创建模型类,进行数据迁移
  2. 创建序列化器
  3. 定义视图函数:调用序列化器,在视图中展示
  4. 定义路由,子应用的分发路由

2. 序列化器-serializer

序列化器的作用:

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

2.1 定义序列化器

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

接下来,为了方便演示序列化器的使用,我们先创建一个新的子应用sers

python manage.py startapp sers
已经有一个数据模型类students/Student

from django.db import models

# Create your models here.
class Student(models.Model):
    name = models.CharField(max_length=100,verbose_name='姓名')
    sex = models.BooleanField(default=1,verbose_name='性别')
    age = models.IntegerField(verbose_name='年龄')
    class_number = models.CharField(max_length=5,verbose_name='班级签名')
    description = models.TextField(max_length=1000,verbose_name='个性签名')

    def __str__(self):
        return self.name

    class Meta:
        db_table="tb_student"
        # 一个是单数一个是复数
        verbose_name="学生"
        verbose_name_plural=verbose_name

为这个模型类提供一个序列化器,先新建一个serializers.py文件,定义如下

from rest_framework import serializers


class StudentSerializer(serializers.Serializer):
    # 学生信息序列化工具
    # 1.设定需要序列化的字段

    id= serializers.IntegerField()
    name = serializers.CharField()
    age = serializers.IntegerField()
    sex = serializers.BooleanField()
    description = serializers.CharField()

    # 2.声明调用的模型信息
    # 3.验证代码
    # 4.添加以及更新模型的代码

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

常用字段类型

字段 字段构造方式
BooleanField BooleanField()
NullBooleanField NullBooleanField()
CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
URLField URLField(max_length=200, min_length=None, allow_blank=False)
UUIDField UUIDField(format='hex_verbose') format: 1) 'hex_verbose'"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex'"5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
IPAddressField IPAddressField(protocol='both', unpack_ipv4=False, **options)
IntegerField IntegerField(max_value=None, min_value=None)
FloatField FloatField(max_value=None, min_value=None)
DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationField DurationField()
ChoiceField ChoiceField(choices) choices与Django的用法相同
MultipleChoiceField MultipleChoiceField(choices)
FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListField ListField(child=, min_length=None, max_length=None)
DictField DictField(child=)

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第17张

Django-DRF组件学习-环境安装与配置与序列化器学习 随笔 第18张

2.2 创建创建Serializer对象

定义好Serializer类后,就可以创建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,或者把客户端发送过来的数据转换字典.

1.3 序列化器的使用

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

  1. 在客户端请求时,使用序列化器可以完成对数据的反序列化。

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

1.3.1 序列化

1.3.1.1 基本使用

(1.)查询学生获取一个数据

from students.models import Student

student = Student.objects.get(id=3)

(2.)构造序列化器对象

from .serializers import StudentSerializer

serializer = StudentSerializer(instance=student)

(3.)获取序列化数据

通过data属性可以获取序列化后的数据

serializer.data
# {'id': 4, 'name': '小张', 'age': 18, 'sex': True, 'description': '猴赛雷'}

完整视图代码

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)

(4.)如果要被序列化的是包含多条数据的查询集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', '猴赛雷')])]

1.3.2 反序列化器

反序列化主要的作用为

  • 数据验证:在数据段的基本验证之外添加自己独有的验证
  • 保存数据:对验证后的数据进行数据保存

1.3.2.1 数据验证

使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。

在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。

验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。

验证成功,可以通过序列化器对象的validated_data属性获取数据。

在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。

为了方便演示效果,我们单独再次创建一个子应用unsers。

python manage.py startapp unsers

定义序列化器代码:

from rest_framework import serializers
class StudentSerializer(serializers.Serializer):
    # 需要转换的字段声明
    # 小括号里面声明主要提供给反序列化使用的
    name = serializers.CharField(required=True, max_length=20)
    age = serializers.IntegerField(max_value=150, min_value=0,required=True)
    sex = serializers.BooleanField(default=True)
    description = serializers.CharField(required=False,allow_null=True, allow_blank=True)
    # 如果序列化器调用的模型中的字段声明,则需要声明Meta类

    # 验证

    # 添加和更新代码

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

# Create your views here.
from django.http import JsonResponse
from django.views import View
from .serializers import StudentSerializer
from students.models import Student
class StudentView(View):
    def post(self,request):
        """添加一个学生"""
        # 接受参数
        post_data = request.POST
        data = {
            "name":post_data.get('name'),
            "age":post_data.get('age'),
            "sex":post_data.get('sex'),
            "description":post_data.get('description'),
        }
        # 调用序列化器进行反序列化验证和转换
        serializer = StudentSerializer(data=data)

        # 当验证失败时,可以直接通过声明 raise_exception=True 让django直接跑出异常
        result = serializer.is_valid(raise_exception=True)
        print( "验证结果:%s" % result )

        # 获取通过验证后的数据
        print( serializer.validated_data )
        # 保存数据
        student = Student.objects.create(
            name=serializer.validated_data.get("name"),
            age=serializer.validated_data.get("age"),
            sex=serializer.validated_data.get("sex")
        )

        print(student)
        # 返回响应结果给客户端
        # alt + enter,可以实现快速导包
        return JsonResponse({"message": "ok"})

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 StudentSerializer(serializers.Serializer):
    """学生数据序列化器"""
    ...

    # 序列化器中可以自定义单个字段的验证方法  def validate_<字段名>(用户提交的字段数据):
    def validate_name(self,data):
        if(data=="老男孩"):
            raise serializers.ValidationError("用户名不能是老男孩")

        # 验证完成以后务必要返回字段值
        return data
2) validate

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

class StudentSerializer(serializers.Serializer):
    """学生数据序列化器"""
    ...

    # 方法名时固定的,用于验证多个字段,参数就是实例化序列化器类时的data参数
    def validate(self,data):
        name = data.get("name")
        if(name == "python"):
            raise serializers.ValidationError("用户名不能是python")

        age = data.get("age")
        if(age==0):
            raise serializers.ValidationError("年龄不能是0")

        # 验证完成以后务必要返回data
        return data
3) validators

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

def check_age(age):
    if age ==50:
        raise serializers.ValidationError("年龄不能刚好是50")
    return age

class StudentSerializer(serializers.Serializer):
    # 需要转换的字段声明
    # 小括号里面声明主要提供给反序列化使用的
    name = serializers.CharField(required=True, max_length=20)
    age = serializers.IntegerField(max_value=150, min_value=0,required=True,validators=[check_age])
    sex = serializers.BooleanField(default=True)
    description = serializers.CharField(required=False,allow_null=True, allow_blank=True)


a

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄