Djangorestframework之前戏

我们首先来看django的请求生命周期

-先进入实现了wsgi协议的web服务器----》进入django---》中间件---》路由---》视图---》取模板,取数据,用数据渲染模板---》返回模板的字符串---》在浏览器上看到页面了

这里我们不妨来看看wsgire协议和CGI协议

CGI是比较原始的开发动态网站的方式。你可以想象一下,一个网站的动态内容肯定是程序生成的,光是静态的html页面无法达到这个效果。那么,这个程序就需要接受客户端的请求,然后进行相应处理,再返回给客户端,客户端和服务端的通信当然是通过HTTP协议。然后我们会发现,这个程序在处理客户端请求的时候,大部分时候会进行很多重复的工作,比如说HTTP请求的解析。也就是说,你的程序需要解析HTTP请求,我的程序也需要解析。于是为了DRY原则,Web服务器诞生了。(以下所说的都是CGI的工作模式)

于是Web服务器可以解析这个HTTP请求,然后把这个请求的各种参数写进进程的环境变量,比如REQUEST_METHOD,PATH_INFO之类的。之后呢,服务器会调用相应的程序来处理这个请求,这个程序也就是我们所要写的CGI程序了。它会负责生成动态内容,然后返回给服务器,再由服务器转交给客户端。服务器和CGI程序之间通信,一般是通过进程的环境变量和管道。这样做虽然很清晰,但缺点就是每次有请求,服务器都会fork and exec,每次都会有一个新的进程产生,开销还是比较大的。原因在与CGI程序是一个独立的程序,它是可以独立运行的(在提供HTTP请求的情况下),它可以用几乎所有语言来写,包括perl,c,lua,python等等。所以对于一个程序,服务器只能以fork and exec的方式来调用它了。

WSGI是Web Server Gateway Interface的缩写。以层的角度来看,WSGI所在层的位置低于CGI。但与CGI不同的是WSGI具有很强的伸缩性且能运行于多线程或多进程的环境下,这是因为WSGI只是一份标准并没有定义如何去实现。实际上WSGI并非CGI,因为其位于web应用程序与web服务器之间,而web服务器可以是CGI,mod_python(注:现通常使用mod_wsgi代替),FastCGI或者是一个定义了WSGI标准的web服务器就像python标准库提供的独立WSGI服务器称为wsgiref。

WSGI里的组件分为『Server』,『Middleware』和『Application』三种,其中的『Middleware』是『设计模式』里的Decorator(装饰器)。

WSGI规范在PEP-333里讲得很详细:PEP 0333 -- Python Web Server Gateway Interface v1.0 ,但我觉得比理解规范更重要的,是理解其设计目的和工作原理。

WSGI规范写得有点绕,之所以绕, 主要原因可能是没有用『类型提示(Type Hints)』,如果用强类型OOP语言的那种『Interface』和『UML』来解释会清晰很多。

实现了wsgi 协议对应的web服务器就是uwsgi,类似Java中的tomcat 。有兴趣的话可以读一下tomcat原理https://blog.csdn.net/qq_38977097/article/details/81089172

CBV 源码分析

原生django的视图层可以分为两类 FBV和CBV,由于djangorestframework只能够由FBV完成,所以简单来看一下FBV的源码。

在FBV视图里面 ,我们的路由是类加as_view(),但是我们写的类并没有这个属性或方法 ,其实是用了父类(view)的

as_view的方法,

不难看出这就是一个闭包函数,传参给view函数,这时候会走view里面的self.dispatch方法,由于对象没有,只能够走父类(view)的dispatch方法

 dispatch方法只是利用了反射请求方法来分发函数,至此我们对CBV源码有了一个简单认识。看懂这个将对我们理解后面的drf有极大地帮助。

 restful规范

  • REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
  • REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
  • REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
  • 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
  • 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)

下面我们逐条来分析一下restful规范的设计
API与用户的通信协议,总是使用HTTPs协议

2  域名有区分

-https://api.example.com
-https://example.org/api/

3 版本
  可以放在路径中
  可以放在请求头中

4 路径,视网络上任何东西都是资源,均使用名词表示
  https://api.example.com/v1/zoos

5 通过method 区分是什么操作
  get表示获取
  post表示新增
  delete表示删除
  patch/put 表示修改

6 过滤,通过在url上传参的形式传递搜索条件

7 状态码
{"status_code":100}

8 错误处理,应返回错误信息
{"status_code":100,'msg':'登录成功'}
{"status_code":101,'msg':'用户名错误'}

9 返回结果,针对不同操作,服务器向用户返回的结果
  get获取所有资源/get获取一个资源
  127.0.0.1/api/vi/books 获取所有图书
  {"status_code":100,'msg':'获取成功',data:[{},{}]}
  127.0.0.1/api/vi/books/3 获取id为3的图书
  {"status_code":100,'msg':'获取成功',data:{name:xx,....}}
  新增数据,把新增的数据再返回
  修改了数据,返回完整的资源对象
   删除数据,返回一个空文档
10 返回结果中提供链接

{"link": {
  "rel":   "collection https://www.example.com/zoos",
  "href":  "https://api.example.com/zoos",
  "title": "List of zoos",
  "type":  "application/vnd.yourformat+json"
}}

基于原生django开发restful的接口

from django.views import View
from app01 import models
class APIView(View):

    def dispatch(self, request, *args, **kwargs):
        #写一些频率控制的东西
        ret = super().dispatch(request, *args, **kwargs)
        return ret

class Test(APIView):
    # http_method_names=['get']
    def get(self,request, *args, **kwargs):
        return HttpResponse('ok')

djangorestframework

安装下载:pip install djangorestframework

from rest_framework.views import  APIView
class Books(APIView):
    def get(self,request):
        #request是被封装后的request,原生的request在request._request
        #如果想用原生requset中的属性,还是原来的用法,因为Request重写了__getattr__方法
        # 原生django只能处理urlencoded和formdata编码,如果是json格式,原生django是不能处理的,需要自己从body中取出来自行处理
        # request.data 不管前端传数据的编码格式是urlencoded,formdata或者是json,都从里面取值
        # request.data
        #request.query_params  是原来django原生的GET中的数据
        #self.FILES  就是上传的文件
        dic={'name':'lqz','age':30,'height':178,'wife':['liuyifei','dilireba','egon']}
        return JsonResponse(dic)
#在settings.py文件中添加rest_framework,这就是django的一个app。

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', 'rest_framework' ]

我们对drf的源码分析,首先我们定义一个类,这个类继承的事APIView
继承了APIView 之后:
  1 所有的请求都没有csrf的认证了
  2 在APIView中as_view本质还是调用了父类的as_view(View的as_view)
  3 as_view中调用dispatch -----》这个dispatch是APIView的dispatch

 

APIVIew的dispatch方法:
  1 对原生request对象做了一层包装(面向对象的封装),以后再用的request对象都新的request对象
  2 在APIView中self.initial(request, *args, **kwargs),里面有频率控制,权限控制和认证相关
  3 根据请求方法执行咱们写的视图类中的相应方法


这个时候视图类中方法的request对象,已经变成了封装后的request
Request类:
  1 原生的request是self._request
  2 取以post形式提交的数据,从request.data中取(urlencoded,formdata,json格式)
  3 query_params 就是原生request的GET的数据
  4 上传的文件是从FILES中取
  5 (重点)其他的属性,直接request.属性名(因为重写了__getattr__方法)

 

猜你喜欢

转载自www.cnblogs.com/guanlei/p/11116071.html