mixin类和Generic类

导入

from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, ListModelMixin, UpdateModelMixin, DestroyModelMixin
from rest_framework.generics import GenericAPIView

CreateModelMixin 创建

源码路径为 rest_framework —> mixing.py —>CreateModelMixin

class CreateModelMixin(object):
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
# 传入前端传入的数据,进行反序列化
serializer = self.get_serializer(data=request.data) # 判断是否全部都校验通过 通过了就执行下面语句
# raise_exception=True 不通过直接报错,下面也不会执行
serializer.is_valid(raise_exception=True) # 执行perform_create 实际就是.save() 保存
self.perform_create(serializer) # 头部信息忽略
headers = self.get_success_headers(serializer.data) # 遵循规范返回创建对象的数据
# status 状态信息,对应的是一个个状态码
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) def perform_create(self, serializer):
serializer.save() def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}

视图使用-post

class PublishView(CreateModelMixin,GenericAPIView):
queryset = models.Publish.objects.all() # 内部执行的时候CreateModelMixin调用了serializer_class
serializer_class = PublishSerializers # 执行post请求就说明要添加数据
def post(self, request, *args, **kwargs):
# 执行create 自己没有就执行CreateModelMixin
# 也就是上面的CreateModelMixin源码解析
return self.create(request, *args, **kwargs)

ListModelMixin - 查看多条数据

源码路径为 rest_framework —> mixing.py —>ListModelMixin

class ListModelMixin(object):
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
# 过滤相关
# 这个时候调用了GenericAPIView内的get_queryset
queryset = self.filter_queryset(self.get_queryset()) # 分页相关
page = self.paginate_queryset(queryset) # page不为空的情况下
if page is not None:
# 序列化多条
serializer = self.get_serializer(page, many=True)
# 返回序列化的数据
return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

视图-get-取所有数据

class PublishView(ListModelMixin,GenericAPIView):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)

RetrieveModelMixin 获取单条数据

源码路径为 rest_framework —> mixing.py—>RetrieveModelMixin

class RetrieveModelMixin(object):

    def retrieve(self, request, *args, **kwargs):
# 获取单条
instance = self.get_object()
# 获取到序列化返回
serializer = self.get_serializer(instance)
return Response(serializer.data)

视图-get-取指定数据

class PublishDetailView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers # 获取指定一条
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)

UpdateModelMixin 更新单条数据

源码路径为 rest_framework —> mixing.py—>UpdateModelMixin

class UpdateModelMixin(object):
"""
Update a model instance.
"""
def update(self, request, *args, **kwargs): partial = kwargs.pop('partial', False) # 要序列化单条数据
instance = self.get_object()
# 序列化
serializer = self.get_serializer(instance, data=request.data, partial=partial)
# 校验是否全部通过
serializer.is_valid(raise_exception=True)
# 直接保存
self.perform_update(serializer) if getattr(instance, '_prefetched_objects_cache', None):
instance._prefetched_objects_cache = {} return Response(serializer.data) def perform_update(self, serializer):
serializer.save() def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)

视图 - put- 更新指定数据

class PublishDetailView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers # 更新指定数据
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)

DestroyModelMixin - 删除指定数据

class DestroyModelMixin(object):
def destroy(self, request, *args, **kwargs):
# 获取要删除的数据
instance = self.get_object()
# 直接执行删除
self.perform_destroy(instance)
# 返回信息
return Response(status=status.HTTP_204_NO_CONTENT) def perform_destroy(self, instance):
instance.delete()

视图 - delete- 删除指定数据

class PublishDetailView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers # 删除指定数据
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)

GenericAPIView 通用的apiview

get_queryset(self):

def get_queryset(self):
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
)
# 这个时候的queryset 是传递进来的queryset对象
queryset = self.queryset
# 判断是否是QuerySet,不是QuerySet 自动.all()
# 说明queryset可以直接给它传递一个对象如 models.Publish.objects
if isinstance(queryset, QuerySet):
# Ensure queryset is re-evaluated on each request.
queryset = queryset.all()
# 返回queryset对象
return queryset

generics 里面组合了mixins里面方法和GenericAPIView

导入

from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView

url

url(r'^publish/$', views.publishView.as_view()),
url(r'^publish/(?P<pk>\d+)/$', views.PublishDetailView.as_view())

ListCreateAPIView源码 创建与查询多条

class ListCreateAPIView(mixins.ListModelMixin,
mixins.CreateModelMixin,
GenericAPIView):
# 获取多条
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
# 创建数据
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)

RetrieveUpdateDestroyAPIView源码 查询单条 更新 删除

class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
GenericAPIView):
# 获取指定数据
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
# 更新全部
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
# 局部更新
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
# 删除
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)

视图

from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView

class publishView(ListCreateAPIView):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers class PublishDetailView(RetrieveUpdateDestroyAPIView):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers

ModelViewSet 多种请求映射

导入:

from rest_framework.viewsets import ModelViewSet
  • 路由:
    url(r'^publish/$', views.PublishView.as_view({'get':'list','post':'create'})),
url(r'^publish/(?P<pk>\d+)/$', views.PublishView.as_view({'get':'retrieve','put':'update','delete':'destroy'})),
  • 视图:
from rest_framework.viewsets import ModelViewSet

class PublishView(ModelViewSet):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers # 这里面虽然可以满足方法的请求但是有时候我们会更具业务的需要,去修改,我们可以重写指定的方法,如create等

为什么可以可以做到请求映射?

  • 主要是重写了as_view方法

1.ModelViewSet中唯一不通的就是继承了GenericViewSet,上面的方法中继承的是GenericAPIView 俩者不同

class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
pass

2.GenericViewSet中pass??,继承了之前的GenericAPIView,但是多继承了一个ViewSetMixin

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
pass

3.ViewSetMixin中仔细看as_view 和原生的Django.views.View.as_view的区别,多了一个参数

Django.views.View.as_view
def as_view(cls, **initkwargs):
pass ViewSetMixin.as_view
def as_view(cls, actions=None, **initkwargs):
pass

4.所以路由中配置的字典{'get': 'list', 'post': 'create'}给了actions

 url(r'^publish/$', views.PublishView.as_view({'get': 'list', 'post': 'create'})),
url(r'^publish/(?P<pk>\d+)/$',
views.PublishView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),

5.ViewSetMixin.as_view 源码中如果可以看出如果继承了ViewSetMixin没有传递actions直接就会异常

if not actions:
raise TypeError("The `actions` argument must be provided when "
"calling `.as_view()` on a ViewSet. For example "
"`.as_view({'get': 'list'})`")

6.ViewSetMixin.as_view核心代码,也就是这一段代码让我们的请求直接执行对应的执行函数

def view(request, *args, **kwargs):
self = cls(**initkwargs)
# 调用了传入的actions 赋值给了action_map
self.action_map = actions # {'get': 'list', 'post': 'create'}
# 解压赋值 请求给了method 处理参数给了action
for method, action in actions.items():
# self是自定义的那个路由函数的对象
# 通过反射去对象中找action
# handler就相当于 那个执行方法的内存地址
handler = getattr(self, action) # 反射设置值 把执行方法的内存地址覆盖了请求,每次来请求执行的就是对于的执行函数
setattr(self, method, handler) if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get self.request = request
self.args = args
self.kwargs = kwargs # And continue as usual
return self.dispatch(request, *args, **kwargs)

自定义ViewSetMixin类

  • 相当于映射 指定请求来了执行指定方法
from rest_framework.viewsets import ViewSetMixin
from rest_framework.views import APIView # 要注意继承的顺序如果APIView继承在前按照mro列表先执行它里面的as_views,所以要放在前面
class Test(ViewSetMixin, APIView):
def test(self, request, pk):
print('自定义请求收到参数:', pk)
return Response()

url

url(r'^test/(?P<pk>\d+)/$', views.Test.as_view({'get': 'test'})),

drf 视图源码详解的更多相关文章

  1. [转]【视觉 SLAM-2】 视觉SLAM- ORB 源码详解 2

    转载地址:https://blog.csdn.net/kyjl888/article/details/72942209 1 ORB-SLAM2源码详解 by 吴博 2 https://github.c ...

  2. Spark Streaming揭秘 Day25 StreamingContext和JobScheduler启动源码详解

    Spark Streaming揭秘 Day25 StreamingContext和JobScheduler启动源码详解 今天主要理一下StreamingContext的启动过程,其中最为重要的就是Jo ...

  3. spring事务详解(三)源码详解

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  4. 条件随机场之CRF++源码详解-预测

    这篇文章主要讲解CRF++实现预测的过程,预测的算法以及代码实现相对来说比较简单,所以这篇文章理解起来也会比上一篇条件随机场训练的内容要容易. 预测 上一篇条件随机场训练的源码详解中,有一个地方并没有 ...

  5. [转]Linux内核源码详解--iostat

    Linux内核源码详解——命令篇之iostat 转自:http://www.cnblogs.com/york-hust/p/4846497.html 本文主要分析了Linux的iostat命令的源码, ...

  6. saltstack源码详解一

    目录 初识源码流程 入口 1.grains.items 2.pillar.items 2/3: 是否可以用python脚本实现 总结pillar源码分析: @(python之路)[saltstack源 ...

  7. Shiro 登录认证源码详解

    Shiro 登录认证源码详解 Apache Shiro 是一个强大且灵活的 Java 开源安全框架,拥有登录认证.授权管理.企业级会话管理和加密等功能,相比 Spring Security 来说要更加 ...

  8. udhcp源码详解(五) 之DHCP包--options字段

    中间有很长一段时间没有更新udhcp源码详解的博客,主要是源码里的函数太多,不知道要不要一个一个讲下去,要知道讲DHCP的实现理论的话一篇博文也就可以大致的讲完,但实现的源码却要关心很多的问题,比如说 ...

  9. Activiti架构分析及源码详解

    目录 Activiti架构分析及源码详解 引言 一.Activiti设计解析-架构&领域模型 1.1 架构 1.2 领域模型 二.Activiti设计解析-PVM执行树 2.1 核心理念 2. ...

随机推荐

  1. redis 教程(一)-基础知识

    redis 简介 redis 是高性能的 key-value 数据库,读的速度是110000次/s,写的速度是81000次/s ,它以内存作为主存储 具有以下优点: 1. 支持数据的持久化,将内存中的 ...

  2. 剑指offer-删除链表中重复的结点-链表-python ***

    题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...

  3. webpack配置--传统多页面项目

    //依赖包--package.json文件 { "name": "webemeet", "version": "1.0.0&quo ...

  4. 多线程 - 内存屏障和cpu缓存

    CPU性能优化 - 缓存 为了提高程序运行的性能,现代CPU在很多方面会对程序进行优化.CPU的处理速度是很快的,内存的速度次之,硬盘速度最慢.在cpu处理内存数据中,内存运行速度太慢,就会拖累cpu ...

  5. 1125. Chain the Ropes (25)

    Given some segments of rope, you are supposed to chain them into one rope. Each time you may only fo ...

  6. php内置函数分析之array_change_key_case()

    PHP_FUNCTION(array_change_key_case) { zval *array, *entry; zend_string *string_key; zend_string *new ...

  7. php 获取真实ip

    REMOTE_ADDR:是和服务器直接"握手"的IP. HTTP_CLIENT_IP:代理服务器添加的 HTTP 头,存放客户端真实IP. HTTP_X_FORWARDED_FOR ...

  8. Jmeter性能测试请求超时:目前遇见有三种情况

    1.请求连接超时.连不上服务器.一般是因为线程太多 2.连接成功,但是读取超时.等不到服务器返回的数据,一般是这次请求查询的量很大,比如查了5度的顶点.(timeout小于server的最大等待时间) ...

  9. 郭盛华现身北京机场,颇有IT男的风范,网友:疑似被招安了

    郭盛华纵横互联网江湖数十年,他白手起家,凭着过人的勇敢.智慧和绝技,身经百战,显赫辉煌,成为中外闻名的互联网安全领域大师级人物. 郭盛华的网络技术指导方面经验丰富实力深厚.他是中国互联网安全领域的传奇 ...

  10. 【usaco 2013 open yinyang】阴阳

    题目 Farmer John 正在在计划自己的农场漫步.他的农场的结构就像一棵树:农场有N个谷仓(1<= N <=100,000),分别由N-1条路链接.这样,他便可以通过这些谷仓间的道路 ...