Play before Djangorestframework

We first look at django request lifecycle

- first into the realization of the web server ---- wsgi agreement "to enter django ---" middleware --- "Routing ---" view --- "take the template, access to data, data rendering template --- "return of the template string ---" you see the page in the browser

Here we take a look at wsgire protocol and CGI protocol

 

 

CGI is a more primitive way of developing dynamic websites. You can imagine the dynamic content of a website must be generated by the program, just a static html page can not achieve this effect. Then, the program would need to accept the client's request, and then be processed, and then returned to the client, the client and server communications, of course, by the HTTP protocol. Then we will find this program in dealing with client requests, most of the time will be a lot of duplication of work, such as parsing HTTP request. In other words, your program needs to parse HTTP request, my program also needs to resolve. So in order to DRY principle, Web server was born. (The following are CGI said operating mode)

So Web server can resolve the HTTP request, and then written into various parameters of the request process environment, such as REQUEST_METHOD, PATH_INFO and the like. After it, the server calls the appropriate procedures to deal with this request, this program is the CGI programs that we write up. It is responsible for generating dynamic content, then back to the server, and then transferred to the client by the server. Communication between the server and CGI programs, usually through the process of environment variables and pipes. While doing so very clear, but the disadvantage is that every time there is a request, the server will fork and exec, every time there is a new process to produce, the cost is quite large. The reason in the CGI program is a standalone program that can be run independently (in the case of providing HTTP request), it can be written in almost any language, including perl, c, lua, python, and so on. So for a program to fork and exec server only way to invoke it.

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__方法)

 

 

 

Guess you like

Origin www.cnblogs.com/guanlei/p/11116071.html