复习

1.整体修改与局部修改

# 序列化get (给前端传递参数)  #查询
ser_obj = ModelSerializer(model_obj) #只传递一个参数,默认是instance的参数,查询数据
# 反序列化post save() => create()(数据保存到数据库中) #添加
ser_obj = ModelSerializer(data=model_data) #传递data参数,保存数据
#反序列化put save() => update() #修改(需要传入instance和data参数)
ser_obj = ModelSerializer(instance=model_obj,data=model_data) #默认partial参数是False,整体修改
#反序列化patch partial=True => 匹配字段required=True校验条件
ser_obj = ModelSerializer(instance=model_obj,data=model_data,partial=True) #局部修改

2.群改ListSerializer

ser_obj = ModelSerializer(instance=model_obj,data=model_data,partial=True,many=True)

    # 实现群改功能,反序列化情况下的create、update就不再调用ModelSerializer的
# 而是调用 ModelSerializer.Meta.list_serializer_class 指向的 ListSerializer 类的create、update
# ListSerializer默认只实现了群增的create,要实现群改,必须重写update   #自定义序列化类,重写update方法
class MyListSerializer(ListSerializer):
def update(self, instance, validated_data):
# print(instance) # 要更新的对象们: [obj1, obj2, ...]
# print(validated_data) # 更新的对象对应的数据们: [{}, {}, ...]
# print(self.child) # 服务的模型序列化类 - V2BookModelSerializer
for index, obj in enumerate(instance):
self.child.update(obj, validated_data[index])
return instance class MyModelSerializer(ModelSerializer):
class Meta:
list_serializer_class = MyListSerializer 将两者类建立关联,在MyListSerializer中就可以用self.child拿到MyModelSerializer,进而使用MyModelSerializer中封装好的方法
cls.Meta.list_serializer_class.child = cls

视图类views.py使用context传递参数给序列化类serializers.py

1)在视图类中实例化序列化对象时,可以设置context内容
2)在序列化类中的局部钩子、全局钩子、create、update方法中,都可以用self.context访问视图类传递过来的内容
需求:
# 1) 在视图类views中,可以通过request得到登陆用户request.user
# 2) 在序列化类中,要完成数据库数据的校验与入库操作,可能会需要知道当前的登陆用户,但序列化类无法访问request
# 3) 在视图类中实例化序列化对象时,将request对象传递进去

视图层:views.py  (使用context传递参数到序列化类中)

class Book(APIView):
def post(self, request, *args, **kwargs):
book_ser = serializers.BookModelSerializer(data=request_data,context={'request':request}) #视图层context传递参数
book_ser.is_valid(raise_exception=True)
book_result = book_ser.save()
return Response({
'status': 0,
'msg': 'ok',
'results': serializers.BookModelSerializer(book_result).data
})

序列化层:serializers.py

class BookModelSerializer(ModelSerializer):
class Meta:
model = models.Book
fields = ('name', 'price')
def validate_name(self, value):
print(self.context.get('request').method) #序列化层接收参数
return value

二次封装Response类便于以后每次使用Response

自定义APIResponse

from rest_framework.response import Response

class APIResponse(Response):
def __init__(self, data_status=0, data_msg='ok', results=None, http_status=None, headers=None, exception=False, **kwargs):
# data的初始状态:状态码与状态信息
data = {
'status': data_status,
'msg': data_msg,
}
# data的响应数据体
# results可能是False、0等数据,这些数据某些情况下也会作为合法数据返回
if results is not None:
data['results'] = results
# data响应的其他内容
# if kwargs is not None:
# for k, v in kwargs.items():
# setattr(data, k, v)
data.update(kwargs) super().__init__(data=data, status=http_status, headers=headers, exception=exception) #重写父类Response的__init__方法

视图家族

views:视图
generics:工具视图
mixins:视图工具集
viewsets:视图集 学习曲线
APIView => GenericAPIView => mixins的五大工具类 => generics中的工具视图 => viewsets中的视图集

两个视图基类   APIView和GenericAPIView

1)AIPView

from rest_framework.views import APIView

APIView是REST framework提供的所有视图的基类,继承自Django的View父类。

APIView与View的不同之处在于:

1.传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
2.视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
3.任何APIException异常都会被捕获到,并且处理成合适的响应信息;
4.在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。 支持定义的属性:
authentication_classes 列表或元祖,身份认证类
permissoin_classes 列表或元祖,权限检查类
throttle_classes 列表或元祖,流量控制类

在APIView中仍有get(),post()等其他请求方式的方法

from rest_framework.views import APIView
from rest_framework.response import Response # url(r'^books/$', views.BookListView.as_view()),
class BookListView(APIView):
def get(self, request):
books = BookInfo.objects.all()
serializer = BookInfoSerializer(books, many=True)
return Response(serializer.data)

2)GenericAPIView通用视图类

GenericAPIView是继承APIView的,使用完全兼容APIView,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可以配合一个或多个Mixin扩展类
重点:GenericAPIView在APIView基础上完成了哪些事
1)get_queryset():从类属性queryset中获得model的queryset数据 群操作就走get_queryset()方法(包括群查,群增等)
2)get_object():从类属性queryset中获得model的queryset数据,再通过有名分组pk确定唯一操作对象 单操作就走get_object()方法(包括单查,单增等)
3)get_serializer():从类属性serializer_class中获得serializer的序列化类

支持的属性:

  • 列表视图与详情视图通过:(重点******)
    1. queryset  指明视图需要的数据(model查询数据)
    2. serializer_class  指明视图使用的序列化器 
  • 列表视图使用:
    1. pagination_class 分页控制类 
    2. filter_backends  过滤控制后端      
  • 详情页视图使用:
    1. lookup_field  自定义主键 有名分组的查询,默认是'pk'
    2. lookup_url_kwarg 查询单一数据时url中的参数关键字名称,默认与look_field相同  

提供的方法:(******)

  1.get_queryset()    从类属性queryset中获得model的queryset数据  

  2.get_object()   从类属性queryset中获得model的queryset数据,再通过有名分组pk来确定唯一操作对象。

  3.get_serializer()  从类属性serializer_class中获得serializer的序列化类,主要用来提供给Mixin扩展类使用。

get_serializer源码:

举例:

视图层:views.py

from rest_framework.generics import GenericAPIView
class BookGenericAPIView(GenericAPIView):
queryset = models.Book.objects.filter(is_delete=False)
serializer_class = serializers.BookModelSerializer
lookup_field = 'pk' #先定义好,单查可以使用,默认是pk 自定义主键的有名分组,如果路由有名分组不是pk,这个属性就要自己设置了
# 群取
def get(self, request, *args, **kwargs):
book_query = self.get_queryset() #获取queryset数据(model查询数据)
book_ser = self.get_serializer(book_query, many=True)
book_data = book_ser.data
return APIResponse(results=book_data) # 单取
def get(self, request, *args, **kwargs):
book_query = self.get_object()
book_ser = self.get_serializer(book_query)
book_data = book_ser.data
return APIResponse(results=book_data)

路由层:urls.py

urlpatterns = [
url(r'^v2/books/$', views.BookGenericAPIView.as_view()),
url(r'^v2/books/(?P<pk>.*)/$', views.BookGenericAPIView.as_view()),
]

五个视图扩展类  mixins视图工具集-辅助GenericAPIView

作用:提供了几种后端视图(对数据资源的增删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。

1)mixins有五个工具类文件,一共提供了五个工具类,六个工具方法:单查、群查、单增、单删、单整体改、单局部改
2)继承工具类可以简化请求函数的实现体,但是必须继承GenericAPIView,需要GenericAPIView类提供序列化器与数据库查询的方法(见上方GenericAPIView基类知识点)
3)工具类的工具方法返回值都是Response类型对象,如果要格式化数据格式再返回给前台,可以通过 response.data 拿到工具方法返回的Response类型对象的响应数据

五个工具类:CreateModelMixin(增加),DestroyModelMixin(删除),ListModelMixin(查询,查queryset),RetrieveModelMixin(查询,查对象,针对于存在"pk"),UpdateModelMixin(修改)

1.ListModelMixin(群查)

列表视图扩展类,提供 list 方法快速实现查询视图,返回200状态码。除了查询,该list方法会对数据进行过滤和分页

2.CreateModelMixin(单增)         #注意:没有群增的方法,需要自己手动写(******)

创建视图扩展类,提供create方法快速创建资源的视图,成功返回201的状态码

3.RetrieveModelMixin(单查)

详情视图扩展类,提供retrieve方法,可以快速实现返回一个存在的数据对象。

4.UpdateModelMixin(更新,修改)          #只有单整体改和单局部改,没有群整体改和群局部改

更新视图扩展类,提供update方法,可以快速实现更新一个存在的数据对象,同时也提供partial_update方法,可以实现局部更新。

5.DestoryModelMixin(删除)  一般不怎么用到

删除视图扩展类,提供destory方法,可以快速实现删除一个存在数据对象。

代码示例:

视图层:views.py

from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin
class BookMixinGenericAPIView(ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericAPIView):
  #GenericAPIView提供的序列化器和查询的数据
queryset = models.Book.objects.filter(is_delete=False)
serializer_class = serializers.BookModelSerializer

  
  #单查和群查
def get(self, request, *args, **kwargs):
if 'pk' in kwargs:
response = self.retrieve(request, *args, **kwargs) #单查 RetrieveModelMixin方法
else:
# mixins提供的list方法的响应对象是Response,将该对象格式化为自定义的APIResponse
response = self.list(request, *args, **kwargs) #群查 ListModelMixin
# response的数据都存放在response.data中
return APIResponse(results=response.data)
  #单增
def post(self, request, *args, **kwargs):
response = self.create(request, *args, **kwargs) #CreateModelMixin方法
return APIResponse(results=response.data)
  #单整体修改
def put(self, request, *args, **kwargs):
response = self.update(request, *args, **kwargs) #UpdateModelMixin
return APIResponse(results=response.data)
  #单局部修改
def patch(self, request, *args, **kwargs):
response = self.partial_update(request, *args, **kwargs)
return APIResponse(results=response.data)

路由层:urls.py

urlpatterns = [
url(r'^v3/books/$', views.BookMixinGenericAPIView.as_view()),
url(r'^v3/books/(?P<pk>.*)/$', views.BookMixinGenericAPIView.as_view()),
]

常用功能子类视图   工具视图(继承了GenericAPIView和各种Mixins工具类)

 1)工具视图都是GenericAPIView的子类,且不同的子类继承了不同的工具类
2)工具视图的功能可以满足需求,只需要继承工具视图,并且提供queryset与serializer_class即可
视图 作用 可使用方法 父类
ListAPIView 查询多条数据 get GenericAPIView 
ListModelMixin
CreateAPIView 新增一条数据 post GenericAPIView 
CreateModelMixin
RetrieveAPIView 查询一条数据 get GenericAPIView 
RetrieveModelMixin
UpdateAPIView 修改一条数据 put,patch GenericAPIView 
UpdateModelMixin
DestroyAPIView 删除一条数据 delete GenericAPIView 
DestroyModelMixin
RetrieveUpdateAPIView 单查,更新一条数据 get,put,patch GenericAPIView 
RetrieveModelMixin UpdateModelMixin
RetrieveUpdateDestroyAPIView 单查,更新,删除一条数据 get,put,patch,delete GenericAPIView 
RetrieveModelMixin UpdateModelMixin DestroyModelMixin

           ListCreateAPIView              群查,更新一条       get,post

视图层:views.py

from rest_framework.generics import ListCreateAPIView, UpdateAPIView
class BookListCreatePIView(ListCreateAPIView, UpdateAPIView):
queryset = models.Book.objects.filter(is_delete=False)
serializer_class = serializers.BookModelSerializer

路由层:urls.py

urlpatterns = [
url(r'^v4/books/$', views.BookListCreatePIView.as_view()),
url(r'^v4/books/(?P<pk>.*)/$', views.BookListCreatePIView.as_view()),
]

视图集 viewsetmixin  (注意路由设置)

1.常用视图集父类
  ViewSet
  继承自APIView和ViewSetMixin,没有提供任何方法,需要自己写
  GenericViewSet
  继承GenericAPIView和ViewSetMixin,其中GenericAPIView提供了基础方法,可以直接搭配Mixin扩展类使用,所以我们选这个
  ModelViewSet  
  继承GenericViewset,但同时也包括ListModelMixin、CreateModelMixin等mixin扩展类
1)视图集都是默认优先继承ViewSetMixin类,再继承一个视图类(GenericAPIView或APIView)
2)ViewSetMixin提供了重写的as_view()方法,继承视图集的视图类,配置路由时调用as_view()必须传入 请求名-函数名 映射关系字典
eg: url(r'^v5/books/$', views.BookGenericViewSet.as_view({'get': 'my_get_list'})),
表示get请求会交给my_get_list视图函数处理

路由层:urls.py

urlpatterns = [
# View的as_view():将get请求映射到视图类的get方法
# ViewSet的as_view({'get': 'my_get_list'}):将get请求映射到视图类的my_get_list方法
url(r'^v5/books/$', views.BookGenericViewSet.as_view({'get': 'my_get_list'})),
url(r'^v5/books/(?P<pk>.*)/$', views.BookGenericViewSet.as_view({'get': 'my_get_obj'})),
]

视图层:views.py

from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins #工具集 可以使用list,retrieve等方法
class BookGenericViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet):
queryset = models.Book.objects.filter(is_delete=False)
serializer_class = serializers.BookModelSerializer def my_get_list(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs) def my_get_obj(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)

GenericAPIView与APIView两大继承视图的区别

1)GenericViewSet和ViewSet都继承了ViewSetMixin,as_view都可以配置 请求-函数 映射
2)GenericViewSet继承的是GenericAPIView视图类,用来完成标准的 model 类操作接口
3)ViewSet继承的是APIView视图类,用来完成不需要 model 类参与,或是非标准的 model 类操作接口
post请求在标准的 model 类操作下就是新增接口,登陆的post不满足
post请求验证码的接口,不需要 model 类的参与
案例:登陆的post请求,并不是完成数据的新增,只是用post提交数据,得到的结果也不是登陆的用户信息,而是登陆的认证信息

工具视图集  (工具集和视图集的混合使用)

路由层:urls.py

urlpatterns = [
url(r'^v6/books/$', views.BookModelViewSet.as_view({'get': 'list', 'post': 'create'})),
url(r'^v6/books/(?P<pk>.*)/$', views.BookModelViewSet.as_view({'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),
]

视图层:views.py

from rest_framework.viewsets import ModelViewSet
class BookModelViewSet(ModelViewSet):
queryset = models.Book.objects.filter(is_delete=False)
serializer_class = serializers.BookModelSerializer # 删不是数据库,而是该记录中的删除字段
def destroy(self, request, *args, **kwargs):
instance = self.get_object() # type: models.Book
if not instance:
return APIResponse(1, '删除失败') # 实际操作,在此之前就做了判断
instance.is_delete = True
instance.save()
return APIResponse(0, '删除成功')

路由组件(了解)

from django.conf.urls import include
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
# 所有路由与ViewSet视图类的都可以注册,会产生 '^v6/books/$' 和 '^v6/books/(?P<pk>[^/.]+)/$'
router.register('v6/books', views.BookModelViewSet) urlpatterns = [
# 第一种添加子列表方式
url(r'^', include(router.urls)),
]
# 第二种添加子列表方式
# urlpatterns.extend(router.urls)

DRF框架(五)——context传参,二次封装Response类,两个视图基类(APIView/GenericAPIView),视图扩展类(mixins),子类视图(工具视图),视图集(viewsets),工具视图集的更多相关文章

  1. drf序列化高级、自定义只读只写、序列化覆盖字段、二次封装Response、数据库查询优化(断关联)、十大接口、视图家族

    目录 自定义只读 自定义只写 序列化覆盖字段 二次封装Response 数据库关系分析 断外键关联关系 ORM操作外键关系 ORM四种关联关系 基表 系列化类其他配置(了解) 十大接口 BaseSer ...

  2. 二次封装Response类 | 视图类传递参数给序列化类context

    二次封装Response类 源码: class Response(SimpleTemplateResponse): """ An HttpResponse that al ...

  3. 3.后台配置、环境变量、日志、异常处理、二次封装Response、路由组件

    目录 环境变量 封装logger 封装项目异常处理 二次封装Response模块 路由组件配置 环境变量 dev.py # 环境变量操作:小luffyapiBASE_DIR与apps文件夹都要添加到环 ...

  4. Django(53)二次封装Response

    前言 有时候我们使用drf的Response,会发现默认返回的格式不太友好,每次我们都需要写入以下的格式 return Response({ "status": 0, " ...

  5. 项目依赖模块解决、二次封装Response、后台数据库配置、user模块user表设计、前台创建及配置

    今日内容概要 二次封装Response 后台数据库配置 user模块user表设计 前台创建及配置 内容详细 补充--项目依赖模块 # 导出项目依赖模块和安装项目依赖模块 第三方模块--->导出 ...

  6. DRF (Django REST framework) 中的视图扩展类

    2. 五个扩展类 1)ListModelMixin 列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码. 该Mixin的list方法 ...

  7. scrapy框架3——请求传参

    当使用scrapy爬取的数据不在同一张页面中(一次请求与数据后解析无法获得想要的全部数据),需要请求传参,在第一次解析时实例化item,将item传递,再次将请求到的数据解析后,封装在item中. 关 ...

  8. selenium + python自动化测试unittest框架学习(五)webdriver的二次封装

    因为webdriver的api方法很长,再加上大多数的定位方式是以xpath方式定位,更加让代码看起来超级长,为了使整体的代码看起来整洁,对webdriver进行封装,学习资料来源于虫师的<se ...

  9. vue传参二

    <template> <ul> <li v-for="(value,key,index) in list" :key="index" ...

随机推荐

  1. 链表 | 递归删除不带头结点链表所有x元素

    王道P37 T1 : 设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点. 王道上的答案绝对是错的,我自己想了一个 函数主体 LinkList* del_x(LinkList* prior, ...

  2. P3350 [ZJOI2016]旅行者

    题目描述 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形成n*m个路口 (i,j)(1<=i<=n,1&l ...

  3. An internal error occurred during: "Synchronizing"

    An internal error occurred during: "Synchronizing" “同步”期间发生内部错误. 处理方法 :单个文件进行更新,将无法更新的文件进行 ...

  4. HashMap多线程并发问题分析-正常和异常的rehash1(阿里)

    多线程put后可能导致get死循环 从前我们的Java代码因为一些原因使用了HashMap这个东西,但是当时的程序是单线程的,一切都没有问题.后来,我们的程序性能有问题,所以需要变成多线程的,于是,变 ...

  5. [Beta阶段]第六次Scrum Meeting

    Scrum Meeting博客目录 [Beta阶段]第六次Scrum Meeting 基本信息 名称 时间 地点 时长 第六次Scrum Meeting 19/05/12 大运村寝室6楼 25min ...

  6. MIME类型和Java类型

    MIME类型和Java类型 类型转换Spring Cloud Stream提供的开箱即用如下表所示:“源有效载荷”是指转换前的有效载荷,“目标有效载荷”是指转换后的“有效载荷”.类型转换可以在“生产者 ...

  7. Centos 7.x卸载ibus黑屏修复及fcitx搜狗拼音安装方法

    ibus黑屏修复 百度出来的fcitx安装方法,都要卸载ibus,如果没有注意同时卸载掉的依赖包的话,gnome桌面中的一些关键库也没被卸载. 修复方法很简单,重新安装Gnome sudo yum - ...

  8. kafka外部访问设置

    一.broker参数 broker.id:kafka集群的唯一标识. log.dirs:kafka存储消息日志的目录,多个用逗号隔开,需要保证指定的目录有充足的磁盘空间. zookeeper.conn ...

  9. Vue日常开发问题

    1.sh: webpack-dev-server: command not found 我的公众号:

  10. java只允许输入数字字母下划线中文

    public static void main(String[] args) { Pattern pattern = Pattern.compile("[_0-9a-z]+"); ...