1,DRF框架?

  Django REST framework 框架是一个用于构建Web API 的强大而又灵活的工具。通常简称为DRF框架 或 REST framework。

  Django REST framework 可以帮助我们大大提高REST API  的开发速度,目的就是简化代码

2,序列化和反序列化

  序列化:将程序中的一个数据结构类型转换为其他格式(字典、JSON、XML等),例   如 Django中的模型类对象转换为字典或JSON字符串,这个转换过程我们称为序列化。

  反序列化:将其他格式(字典、JSON、XML等)转换为程序中的数据,例如将JSON字符串或字典转换保存为Django中的模型类对象,这个过程我们称为反序列化

  序列化(侠义):将对象转为字典,json

  反序列化(侠义):将字典,json转换为对象

3,Django REST framework 的使用:

  1,下载安装:pip install djangorestframework

  2,settings中进行注册  INSTALL_APPS     ‘rest_framework’

  3,   DRF 框架序列化:只能将对象转换为字典,不能转换为json

  4,DRF框架反序列化:数据校验,数据保存(新增和更新)  

4,使用序列化器必须先定义序列化器:

  序列化器的定义:

    class <序列化器类名> (serializer.Serailizers):

        字段 = serializers.字段类型(参数)

5,序列化功能:

  1,创建序列化器类对象  serializer = 类名(user) (把对象放入类中)

  2,获取序列化后的数据  res = serializers.data()    print(res)

6,反序列化功能:

  1,创建序列化器对象   serializer = 类名(data={xx}) 把前端传入的字典放入其中

  2,进行参数校验 serializer.is_valid   返回true 或 false  代表校验成功和失败

  3,获取校验失败的错误信息:serializers.errors   如果成功返回的是空字典

  4,获取校验后的数据:serializers.validated_data   返回的是校验成功后的有序字典orderdict

7,序列化器使用的总结:

  1,无论是序列化还是反序列化都需要创建序列化器对象

    serializers = UserSerializer(instance = none,data={})

    序列化时,将序列化对象传给intsance

    反序列化时,将字典传给data

8,序列化器类的通用参数:

  reade_only (该字段只在序列化时使用设为true)

  write_only     (该字段只在反序列化时使用设为true)

  read_only  和 write_only 不指定时为false ,表示序列化和反序列化时都使用

  required 只争对反序列化时使用,默认为true,代表反序列化时必须传入该字段参数,

  default 设置序列化或反序列化时的默认值  

  max_length和min_length:设置反序列化时的最大长度和最小长度

  max_value和min_value:设置反序列化时的最大值和最小值

9,序列化操作

  1,序列化单个对象 

book = BookInfo.objects.get(id=1)
serizlizer = BookInfoSerializer(book)
res = serializer.data

  2,序列化多个对象

books = BookInfo.objects.all()   #Queryset
serializer = BookInfoSerializer(books,many=True)
res = serializer.data

  3,关联对象 嵌套序列化

#1,将关联对象序列化为关联对象的主键
hbook = serializer.PrimarykeyRelatedFiled(label = '图书',read_only = true) 或
hbook = serializer.PrimarykeyRelatedFiled(label = '图书',queryset=BookInfo.objects.all()) #2,使用指定的序列化器将关联对象一并序列化
hbook = BookInfoSerializer() #3,将关联对象序列化为关联对象模型类__str__的返回值
hbook = serializer.StringRelatedFiled(lable='图书')

注意:和一个对象关联的对象如果有多个,在进行嵌套序列化字段定义时,需要加 many=true

10 ,反序列化操作  (可以进行校验和保存)校验只能进行数据是否完整,类型是否正确,以及一些选项参数对data中的数据进行校验 

  1,  补充校验的三种方式:

DRF框架(django rest framework)-LMLPHP

DRF框架(django rest framework)-LMLPHP  

 注意:方式一 :在定义序列化器类外定义一个函数进行校验,在字段后面添加 validators =  函数名 (不常用)

    方法二:在定义序列化器类里添加函数,其中函数名必须是 validate_<字段名>   (缺点是只能对单个字段进行校验)

    方法三 :  在定义序列化器类里添加函数,可以进行多个字段的对比,函数名必须是 validata

  

  2,保存数据:

    前提:必须校验通过ser.is_valid()

    使用:serializer.save()    内部可能会调用序列化器类的create或update方法,(如果序列化器类继承serializer.Serializer,需要重写这两个方法,该父类为实现,如果继承serializer.ModelSerializer,父类已经实现)

    创建序列化器对象时,如果只传入instance,save()方法被调用,否则create()方法被调用(create方法调用时instance和data参数都要传入)

  3,ModelSerializer类的使用

    使用:序列化器需要对应是Django的模型类

    特点:自动生成序列化器类中的字段

        默认已经实现create和update方法

11,APIView视图类

  APIView是View的子类,

  区别:1,请求对象:Request   

request.data  :包含解析之后的请求体中的数据,相当于之前的request.POST  | request.body  | request.FILEs
request.query_params : 包含了解析之后的查询字符串中的数据 QueryDict

      2,响应对象:response(原始的响应数据)

        根据客服端请求头中Accept自动转换为对应的格式,不需要指定,直接返回res.data ,默认返回json

      3, 自动处理APIException的子类异常和Http404

      4,其他权限,认证,权限,限流  (后面细说)

12,GenericAPIView视图类 

class  BookListView(GenericAPIView):
#指定视图所使用的序列化器类
serializer_class = BookInfoSerializer #名字必须是serializer_class,父类已经定义,但为None,需要自己指定 #指定视图所使用的查询集
queryset = BookInfo.objects.all() #名字也是必须是queryset,和上面一样,可以到源码进行查看

  继承genericAPIView后可以调用下面的方法:

  get_serializer_class :  获取指定的序列化器类

  get_serializer :获取指定的序列化器类对象

  get_queryset:获取指定的查寻集

  get_object : 从指定查询集查询一个对象进行返回,默认根据url地址提取的pk进行查询,所以不需要传递参数pk,该函数会制动从url中进行匹配

  注意:使用get_serializer_class 和get_serializer 之前必须先指定serializer_class

     使用get_queryset和get_object必须先指定queryset 属性

  2,GenericAPIView 和APIView 的区别:继承自APIView

    1)  增加操作序列化器相关属性和方法

    2) 增加数据库查询相关属性和方法

    3) 过滤,排序,分页  (后面细说)

  3,GenericAPIView 案例:(增,删,改,查)

#/books/
class BookListView(GenericApIview):
#指定视图使用的序列化器类
serializer_class = BookInfoSerializer() #序列化器类 #指定查询集
queryset = BookInfo.objects.all() #查询所有书籍
def get(self,request):
books = self.get_queryset() # Queryset:查询集
#将所有图书数据通过json进行返回
ser = self.get_serializer(books,many=true) #多个加many=true return Response(ser.data) #ser.data 将序列化后的数据进行返回 #新增书籍
def post(self,request):
#校验前端传入的数据
ser = self.get_serializer(data=request.data)
ser.is_valid(raise_exception=true) #保存数据
ser.save() #调用序列化器类中的create方法 #将新增的图书进行返回
return Response(ser.data,status=status.HTTP_201_CREATE)
class BookDetailView(GenericAPIView):
serializer_class = BookInfoSerializer()
queryset = BookInfo.objects.all() #查找指定图书
def get(self,request,pk):
book = self.get_object() #不用传参数,改函数会自动在url中查找pk的值 ser = self.get_serializer(book) return Response(ser.data) #修改指定图书
def put(self,request,pk):
book = self.get_object() #参数校验
ser = self.get_serializer(book,data=request.data)
ser.is_valid(raise_exception=true)
#校验通过保存数据
ser.save()
return Response(res.data) #删除指定图书
def delete(self,request,pk):
book = self.get_object()
book.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

13 , Mixin扩展类

  继承object,不能单独使用,需要配合GenericAPIView来进行使用

  DRF框架提供5个Mixin扩展类,就是对上面五个函数进行封装:

  

# 自己封装Mixin扩展类
class MyListModelMixin(object):
def list(self, request, *args, **kwargs):
"""封装获取一组数据的通用代码流程"""
query_set = self.get_queryset() # QuerySet:查询集
serializer = self.get_serializer(query_set, many=True)
return Response(serializer.data) class MyCreateModelMixin(object):
def create(self, request, *args, **kwargs):
"""封装新增一条数据通用代码流程"""
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save() # 调用序列化器类中的create
return Response(serializer.data, status=status.HTTP_201_CREATED) # /books/
class BookListView(mixins.ListModelMixin,
mixins.CreateModelMixin,
GenericAPIView):
# 指定视图使用的序列化器类
serializer_class = BookInfoSerializer
# 指定视图使用的查询集
queryset = BookInfo.objects.all() # serializer_class = HeroInfoSerializer
# queryset = HeroInfo.objects.all() def get(self, request):
return self.list(request) def post(self, request):
return self.create(request) class MyRetrieveModelMixin(object):
def retrieve(self, request, *args, **kwargs):
"""封装获取指定数据通用代码流程"""
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data) # obj = MyRetrieveModelMixin()
# obj.retrieve() class MyUpdateModelMixin(object):
def update(self, request, *args, **kwargs):
"""封装修改指定数据通用代码流程"""
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save() # 调用序列化器类中的update
return Response(serializer.data) class MyDestroyModelMixin(object):
def destroy(self, request, *args, **kwargs):
"""封装删除指定数据的通用代码流程"""
instance = self.get_object()
instance.delete()
return Response(status=status.HTTP_204_NO_CONTENT) # 系统封装的
# /books/(?P<pk>\d+)/
# /books/100/
class BookDetailView(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
GenericAPIView):
serializer_class = BookInfoSerializer
queryset = BookInfo.objects.all() def get(self, request, pk):
return self.retrieve(request, pk) def put(self, request, pk):
return self.update(request, pk) def delete(self, request, pk):
return self.destroy(request, pk)

14,子类视图:

  继承了GenericAPIView和对应的Mixin扩展类,而且还提供了对应的请求处理函数(get,post)

class BookListView(ListAPIView):
serializer_class = BookInfoSerializer
queryset = BookInfo.objects.all()

15,视图集:

  概念:将一组相关的API接口放在同一个类中,这个类就叫视图集。

  基本使用: 

1,继承父类ViewSet
2, 视图集中处理方法不以请求方发命名(get,..),而是以对应的操作命名:list,create,retrieve,update,destroy
3, 进行url地址配置时,需要指明请求方式,请求url地址时对应的处理方法

  视图集父类:

  ViewSet(继承ViewSetMixin和APIView)

  GenericViewSet(继承ViewSetMixin和GenericAPIView)   可以配合Mixin扩展类来提供对应的处理函数

  ModelViewSet(继承GenericviewSet和5个Mixin扩展类)  常用

  ReadOnlymodelViewSet(继承GenericViewSet和2个Mixin扩展类) (ListModelMixin和RetievemodelMixin)

视图集添加额外的API方法即可,注意不要和其他API方法名有冲突 

* 直接在视图集中添加API方法即可,注意不要和其他API方法名有冲突
* 添加之后需要进行url地址配置

16,路由router

  作用:动态生成视图集中API接口的url 配置项

  使用:

DRF框架(django rest framework)-LMLPHP

lookup_value_regex:

  设置router生成路由时,从url中提取pk参数对应的正则表达式

视图集中额外API接口配置项生成:

需要添加action装饰器(导入 from rest_framework.decorators import action)

DRF框架(django rest framework)-LMLPHP

注意:detail = true或false,看是否需要从url中提取PK,需要就设置为true

defaultRouter和SimpleRouter区别:

1,DefaultRouter多生成一个根路径/配置项

2,每个配置项都可以直接根据.json,返回json数据

17 ,认证 | 权限 | 限流

  1,认证:

  DRF框架默认全局支持两种认证方法:session认证和基本认证

  可以修改全局的认证方式:

  

REST_FRAMEWORK = {
# 修改全局认证方式
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication', # 仅支持session认证
),
}

DRF框架(django rest framework)-LMLPHP

# 指定视图自己的认证方式,此处仅支持session认证
authentication_classes = [SessionAuthentication]

  权限:

  1,DRF框架默认全局权限设置为:AllowAny,代表允许所有人访问

  2,可以修改全局的权限控制方式

REST_FRAMEWORK = {
# 修改全局权限控制方式
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', # 允许认证用户
)
}

DRF框架(django rest framework)-LMLPHP

 指定视图自己的权限控制方式,此处代表只有认证过的用户才能访问本视图集中的接口
 permission_classes = [IsAuthenticated]

  3,自定义权限控制类

class MyPermission(BasePermission):
def has_permission(self, request, view):
"""判断用户对使用这个权限控制类的视图中的API接口是否有访问权限"""
return True def has_object_permission(self, request, view, obj):
"""判断用户对使用这个权限控制类中视图中某个对象是否有访问权限"""
# get_object:
# 需求:id为1或3的对象用户可以访问,其他的对象不允许访问
if obj.id in (1, 3):
return True
return False

DRF框架(django rest framework)-LMLPHP

 

限流:限制用户访问接口的频率

  1,分别限流

REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
# 针对未登录(匿名)用户的限流控制类
'rest_framework.throttling.AnonRateThrottle',
# 针对登录(认证)用户的限流控制类
'rest_framework.throttling.UserRateThrottle'
),
# 指定限流频次
'DEFAULT_THROTTLE_RATES': {
# 认证用户的限流频次
'user': '5/minute',
# 匿名用户的限流频次
'anon': '3/minute',
},
}

DRF框架(django rest framework)-LMLPHP

统一限流:

REST_FRAMEWORK = {
# 针对匿名用户和认证用户进行统一的限流控制
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle',
), # 指定限流频次选择项
'DEFAULT_THROTTLE_RATES': {
'upload': '3/minute',
'contacts': '5/minute'
},
}

DRF框架(django rest framework)-LMLPHP

  统一限流,还需要在视图中通过属性throttle_scope指定限流选项

18 ,过滤 | 排序 | 分页

过滤:

  1,安装:pip install django-filter

  2,注册子应用,添加过滤配置

  3,在视图中通过filter_fields属性指定过滤字段

排序:

  在视图中排序设置:(前端在查询字符串中指定排序字段,http://xxxx.com/?ordering=id)

  DRF框架(django rest framework)-LMLPHP

分页:

  设置全局分页类

REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 5 # 页容量
}

DRF框架(django rest framework)-LMLPHP

注意:设置全局分页类之后,默认情况下凡是使用ListModelMixin中的List返回数据的API,都会使用全局分页类进行分页,如果要取消,可以在该视图中设置:

  pagination_class = None

自定义分页类;

DRF框架(django rest framework)-LMLPHP

# ?page=<页码>&pagesize=<页容量>
class StandardResultPagination(PageNumberPagination):
# 默认分页页容量
page_size = 3
# 指定页容量参数的名称
page_size_query_param = 'pagesize'
# 分页最大页容量
max_page_size = 5

注意:自定义分页类可以设置为全局分页类或指定视图自己使用的分页类

19,异常处理

  只要继承了APIView或者它的子类,视图中的处理异常:APIException子类异常或HTTP404,DRF框架都可以自动处理

自定义异常处理函数:

DRF框架(django rest framework)-LMLPHP

from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
from rest_framework import status
from django.db import DatabaseError def exception_handler(exc, context):
# 调用DRF框架默认异常处理函数
response = drf_exception_handler(exc, context) if response is None:
# DRF框架不能处理此异常,自己处理:DatabaseError
if isinstance(exc, DatabaseError):
response = Response({'detail': '数据库错误!!!'}, status=status.HTTP_507_INSUFFICIENT_STORAGE) return response

复制代码

修改EXCEPTION_HANDLER配置项

REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'booktest.utils.exceptions.exception_handler'
}
05-07 15:13
查看更多