Django Rest Framework 视图和路由

 

DRF的视图

APIView

我们django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们两个有什么不同呢~~~

urlpatterns = [
url(r'^book$', BookView.as_view()),
url(r'^book/(?P<id>\d+)$', BookEditView.as_view()),
]

我们可以看到,不管是View还是APIView最开始调用的都是as_view()方法~~那我们走进源码看看~~

我们能看到,APIView继承了View, 并且执行了View中的as_view()方法,最后把view返回了,用csrf_exempt()方法包裹后去掉了csrf的认证。

那我们看看View中的as_view()方法做了什么~

我们看到了~在View中的as_view方法返回了view函数,而view函数执行了self.dispatch()方法~~但是这里的dispatch方法应该是我们APIView中的~~

我们去initialize_request中看下把什么赋值给了request,并且赋值给了self.request, 也就是我们在视图中用的request.xxx到底是什么~~

我们看到,这个方法返回的是Request这个类的实例对象~~我们注意我们看下这个Request类中的第一个参数request,是我们走我们django的时候的原来的request~

我们看到了,这个Request类把原来的request赋值给了self._request, 也就是说以后_request是我们老的request,新的request是我们这个Request类~~

那我们继承APIView之后请求来的数据都在哪呢~~

我们用了rest_framework框架以后,我们的request是重新封装的Request类~

request.query_params 存放的是我们get请求的参数

request.data 存放的是我们所有的数据,包括post请求的以及put,patch请求~~~

相比原来的django的request,我们现在的request更加精简,清晰了~~~

现在我们知道了APIView和View的一些区别~~当然还有~~后面我们还会说~~

我们写的视图可能对多个表进行增删改查,就导致我们的视图特别多重复的代码~~

那么我们尝试着来进行封装一下~~

第一次封装

APIView视图

class BookView(APIView):

    def get(self, request):
query_set = Book.objects.all()
book_ser = BookSerializer(query_set, many=True)
return Response(book_ser.data) def post(self, request):
query_set = request.data
book_ser = BookSerializer(data=query_set)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.validated_data)
else:
return Response(book_ser.errors) class BookEditView(APIView): def get(self, request, id):
query_set = Book.objects.filter(id=id).first()
book_ser = BookSerializer(query_set)
return Response(book_ser.data) def patch(self, request, id):
query_set = Book.objects.filter(id=id).first()
book_ser = BookSerializer(query_set, data=request.data, partial=True)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.validated_data)
else:
return Response(book_ser.errors) def delete(self, request, id):
query_set = Book.objects.filter(id=id).first()
if query_set:
query_set.delete()
return Response("")
else:
return Response("删除的书籍不存在")

第一次封装

class GenericAPIView(APIView):
queryset = None
serializer_class = None def get_queryset(self):
return self.queryset.all() def get_serializer(self, *args, **kwargs):
return self.serializer_class(*args, **kwargs) class ListModelMixin(object):
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data) class CreateModelMixin(object):
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.validated_data)
else:
return Response(serializer.errors) class RetrieveModelMixin(object):
def retrieve(self, request, id, *args, **kwargs):
book_obj = self.get_queryset().filter(pk=id).first()
book_ser = self.get_serializer(book_obj)
return Response(book_ser.data) class UpdateModelMixin(object):
def update(self, request, id, *args, **kwargs):
book_obj = self.get_queryset().filter(pk=id).first()
book_ser = self.get_serializer(book_obj, data=request.data, partial=True)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.validated_data)
else:
return Response(book_ser.errors) class DestroyModelMixin(object):
def destroy(self, request, id, *args, **kwargs):
queryset = self.get_queryset()
try:
queryset.get(pk=id).delete()
return Response("")
except Exception as e:
return Response("信息有误")
# 我们把公共的部分抽出来 这样不管写多少表的增删改查都变的很简单
# 这样封装后我们的视图会变成这样 class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs) class BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request, id, *args, **kwargs):
return self.retrieve(request, id, *args, **kwargs) def patch(self, request, id, *args, **kwargs):
return self.update(request, id, *args, **kwargs) def destroy(self, request, id, *args, **kwargs):
return self.delete(request, id, *args, **kwargs) 第一次封装

我们封装的GenericAPIView,包括封装每个方法的类,其实框架都帮我们封装好了~~

我们可以直接继承这些类~~来实现上面的视图~~可是还有没有更简单的方法呢~我们再次封装一下~~

第二次封装

# 上面我们写的继承类太长了~~我们再改改

class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
pass class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
pass class BookView(ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs) class BookEditView(RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request, id, *args, **kwargs):
return self.retrieve(request, id, *args, **kwargs) def patch(self, request, id, *args, **kwargs):
return self.update(request, id, *args, **kwargs) def delete(self, request, id, *args, **kwargs):
return self.delete(request, id, *args, **kwargs) 第二次封装

这次我们只是让继承变的简单了一点而已,好像并没有什么大的进步~~

我们可不可以把这两个视图合并成一个视图呢~~~框架给我们提供了一个路由传参的方法~~

我们看下ViewSetMixin

actions这个默认参数其实就是我们路由可以进行传参了~~~

下面这个循环~可以看出~我们要传的参数是一个字段~key应该是我们的请求方式,value应该对应我们处理的方法~

这样我们每个视图就不用在写函数了~因为已经和内部实现的函数相对应了~

第三次封装

路由urls.py

urlpatterns = [
# url(r'^book$', BookView.as_view()),
# url(r'^book/(?P<id>\d+)$', BookEditView.as_view()),
url(r'^book$', BookView.as_view({"get": "list", "post": "create"})),
url(r'^book/(?P<pk>\d+)$', BookView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),
]

第三次封装

from rest_framework.viewsets import ViewSetMixin

# class BookView(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
# queryset = Book.objects.all()
# serializer_class = BookSerializer # 如果我们再定义一个类
class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
pass class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer

我们现在的视图就只要写两行就可以了~~~

其实我们写的所有的视图~框架都帮我们封装好了~

注意一点~~用框架封装的视图~我们url上的那个关键字参数要用pk~~系统默认的~~

奉献一张图来看下我们的继承顺序~~~

DRF的路由

我们上面的路由传参写的特别多~~框架也帮我们封装好了~

路由

from .views import BookView
from rest_framework.routers import DefaultRouter router = DefaultRouter()
router.register(r"book", BookView) urlpatterns = [
# url(r'^book$', BookView.as_view()),
# url(r'^book/(?P<id>\d+)$', BookEditView.as_view()),
# url(r'^book$', BookView.as_view({"get": "list", "post": "create"})),
# url(r'^book/(?P<pk>\d+)$', BookView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})), ]
urlpatterns += router.urls

我们可以看到~~通过框架我们可以把路由视图都变的非常简单~~

但是需要自定制的时候还是需要我们自己用APIView写~~当不需要那么多路由的时候~也不要用这种路由注册~~

总之~~一切按照业务需要去用~~~

Django Rest Framework 视图和路由的更多相关文章

  1. 03 Django REST Framework 视图和路由

    01-DRF中的request 在Django REST Framework中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等. 比如,区别 ...

  2. python 全栈开发,Day96(Django REST framework 视图,django logging配置,django-debug-toolbar使用指南)

    昨日内容回顾 1. Serializer(序列化) 1. ORM对应的query_set和ORM对象转换成JSON格式的数据 1. 在序列化类中定义自定义的字段:SerializerMethodFie ...

  3. [Django REST framework - 视图组件之视图基类、视图扩展类、视图子类、视图集]

    [Django REST framework - 视图组件之视图基类.视图扩展类.视图子类.视图集] 视图继承关系 详图见文章末尾 视图组件可点我查看 两个视图基类:APIView.GenericAP ...

  4. Django REST framework - 视图

    目录 Django REST framework 视图GenericAPIView GenericAPIView 例子 属性 混入 具体视图类 自定义基类 Django REST framework ...

  5. Django的View(视图)和路由系统

    一.Django的View(视图) 1.介绍 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一 ...

  6. Django REST framework视图

    混合类阶段(封装2次) 路由: url(r'school/$', views.SchoolView.as_view()), url(r'school/(?P<pk>\d+)/$', vie ...

  7. rest framework 视图,路由

    视图 在上面序列化的组件种已经用到了视图组件,即在视图函数部分进行逻辑操作. 但是很明显的弊端是,对每个表的增删改查加上 单条数据,需要用到 2个类 5个方法(增删改查,单数据查)才可以完整的实现,当 ...

  8. DRF (Django REST framework) 中的路由Routers

    路由Routers 注意是:对于视图集ViewSet!!!我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息. REST frame ...

  9. DRF 视图组件,路由组件

    视图组件  -- 第一次封装   -- GenericAPIView(APIView):    queryset = None    serializer_class = None    def ge ...

随机推荐

  1. leetcode 189 旋转数组

    class Solution(object): def rotate(self, nums, k): """ :type nums: List[int] :type k: ...

  2. 日志监控文件中获取ip,每一分钟统计一次,超过200次的计入黑名单

    一.日志文件access.log #.要从日志里面找到1分钟之内访问超过200次的 #.每分钟都运行一次 #.读取文件内容,获取到ip地址 #.把每个ip地址存起来{} #.判断ip访问的次数是否超过 ...

  3. 图片转成base64位 页面中图片展示

    <img src="data:image/gif;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAABG ...

  4. jquery---筛选总结

    jQuery中筛选这块内容较多,就简单的说明一下说用方法和能有什么样效果,就不弄案例来说明了: 第一类:过滤 1.eq(index|-index) $("p").eq(1).css ...

  5. 一次请求中,经过 nginx+uWSGI+flask应用程序搭建服务的执行过程

    Flask框架有自带的http server,但是缺点非常明显,并发能力,及时响应非常差,只适合开发时自测使用. 在我接触过的项目中,生产环境使用nginx+uWSGI+flask应用程序进行部署服务 ...

  6. Git命令行入门

    安装 下载与文档地址:https://git-scm.com/book/zh/v2 我使用的是linux系统,故使用命令行安装Git # apt-get install git 配置 # git co ...

  7. DLC 数制与数制的转换

    进位计数值:用进位的方法进行计数 常用数值有十进制.二进制.八进制.十六进制等. 进位计数制把包括基数与权两个基本问题.

  8. [UnityShader基础]07.MaterialPropertyDrawer

    参考链接: https://blog.csdn.net/e295166319/article/details/60141677 https://docs.unity3d.com/ScriptRefer ...

  9. 关于No qualifying bean of type [XXX.XXX] found for dependency 的一次记录

    异常开始于spring+springmvc+mybatis 注解配置,启动tomcat服务器出现No qualifying bean of type [com.***.service] found f ...

  10. 安装FrameWork后重新注册IIS

    IIS和.netfw4.0安装顺序是从前到后,如果不小心颠倒了,无所谓. 打开程序-运行-cmd:输入一下命令重新注册IIS C:\WINDOWS\Microsoft.NET\Framework\v4 ...