Django框架深刻了解_01(Django请求生命周期、开发模式、cbv源码分析、restful规范、跨域、drf的安装及源码初识)

1、Django请求生命周期:

前端发出请求到后端,经过Django处理、响应返回给前端相关结果的过程html

先进入实现了wsgi协议的web服务器--->进入django中间件--->路由f分发--->视图(CBV或FBV)---->取模板,取数据,用数据渲染模板--->返回模板的字符串---->前端页面获得数据展示页面给用户前端

2、WEB开发模式:

在开发Web应用中,有两种应用模式:web

先后端不分离
先后端分离
1 先后端不分离
在先后端不分离的应用模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端须要控制前端的展现,前端与后端的耦合度很高。ajax

这种应用模式比较适合纯网页应用,可是当后端对接App时,App可能并不须要后端返回一个HTML网页,而仅仅是数据自己,因此后端本来返回网页的接口再也不适用于前端App应用,为了对接App后端还需再开发一套接口。django

2 先后端分离
在先后端分离的应用模式中,后端仅返回前端所需的数据,再也不渲染HTML页面,再也不控制前端的效果。至于前端用户看到什么效果,从后端请求的数据如何加载到前端中,都由前端本身决定,网页有网页的处理方式,App有App的处理方式,但不管哪一种前端,所需的数据基本相同,后端仅需开发一套逻辑对外提供数据便可。json

在先后端分离的应用模式中 ,前端与后端的耦合度相对较低。后端

在先后端分离的应用模式中,咱们一般将后端开发的每一个视图都称为一个接口,或者API,前端经过访问接口来对数据进行增删改查。api

3、cbv源码分析:

cbv--基于类的视图,一开始咱们写视图层的时候是基于函数来处理前端请求数据FBV,这只是一种方法,更经常使用的还有在视图层使用类的方法来创建视图层跨域

cbv流程:数组

建立路由

url(r'^test/', views.Test.as_view()),

--->建立类的视图

class Test(View):
    def get(self,request):
        return HttpResponse('cbv_get')
    
    def post(self,request):
        return HttpResponse('cbv_post')

前端请求经过中间件进入路由--->根据路由匹配,成功后会执行后面的Test.as_view()函数,而as_view()在Django启动的时候就会自动执行返回一个view的函数内存地址,此时路由匹配成功就会view加括号执行该函数,而view内部又调用了self.dispatch函数方法,dispatch会根据请求的方式不一样,执行咱们定义的类中对应请求名称的函数方法(好比get请求,就会执行类中get的函数方法)

4、认识RESTful

即Representational State Transfer的缩写。维基百科称其为“具象状态传输”,国内大部分人理解为“表现层状态转化”。

RESTful是一种开发理念。维基百科说:REST是设计风格而不是标准。 REST描述的是在网络中client和server的一种交互形式;REST自己不实用,实用的是如何设计 RESTful API(REST风格的网络接口),一种万维网软件架构风格。

咱们先来具体看下RESTful风格的url,好比我要查询商品信息,那么

非REST的url:http://.../queryGoods?id=1001&type=t01

REST的url: http://.../t01/goods/1001

能够看出REST特色:url简洁,将参数经过url传到服务器,而传统的url比较啰嗦,并且现实中浏览器地址栏会拼接一大串字符,想必大家都见过吧。可是采用REST的风格就会好不少,如今不少的网站已经采用这种风格了,这也是潮流方向,典型的就是url的短化转换。

那么,到底什么是RESTFul架构: 若是一个架构符合REST原则,就称它为RESTful架构。

要理解RESTful架构,理解Representational State Transfer这三个单词的意思。

具象的,就是指表现层,要表现的对象也就是“资源”,什么是资源呢?网站就是资源共享的东西,客户端(浏览器)访问web服务器,所获取的就叫资源。好比html,txt,json,图片,视频等等。

表现,好比,文本能够用txt格式表现,也能够用HTML格式、XML格式、JSON格式表现,甚至能够采用二进制格式;图片能够用JPG格式表现,也能够用PNG格式表现。

浏览器经过URL肯定一个资源,可是如何肯定它的具体表现形式呢?应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述。

状态转换, 就是客户端和服务器互动的一个过程,在这个过程当中, 势必涉及到数据和状态的变化, 这种变化叫作状态转换。

互联网通讯协议HTTP协议,客户端访问必然使用HTTP协议,若是客户端想要操做服务器,必须经过某种手段,让服务器端发生"状态转化"(State Transfer)。

HTTP协议实际上含有4个表示操做方式的动词,分别是 GET,POST,PUT,DELETE,他们分别对应四种操做。GET用于获取资源,POST用于新建资源,PUT用于更新资源,DElETE用于删除资源。GET和POST是表单提交的两种基本方式,比较常见,而PUT和DElETE不太经常使用。

并且HTTP协议是一种无状态协议,这样就必须把全部的状态都保存在服务器端。所以,若是客户端想要操做服务器,必须经过某种手段,让服务器端发生"状态转化"(State Transfer)

总结
综合上面的解释,RESTful架构就是:

每个URL表明一种资源;
客户端和服务器之间,传递这种资源的某种表现层;
客户端经过四个HTTP动词,对服务器端资源进行操做,实现"表现层状态转化"。

RESTful规范

  • API与用户的通讯协议,老是使用HTTPs协议
  • 域名 
    • https://api.example.com                         尽可能将API部署在专用域名(会存在跨域问题)
    • https://example.org/api/                         API很简单
  • 版本
    • URL,如:https://api.example.com/v1/
    • 请求头                                                  跨域时,引起发送屡次请求
  • 路径,视图网络上任何东西都是资源,均使用名词表示(可复数)
    • https://api.example.com/v1/zoos
    • https://api.example.com/v1/animals
    • https://api.example.com/v1/employees
  • method,经过请求方式method 区分是什么操做
    • GET      :从服务器取出资源(一项或多项)
    • POST    :在服务器新建一个资源
    • PUT/PATCH   :在服务器更新资源
    • DELETE :从服务器删除资源
  • 过滤,经过在url上传参的形式传递搜索条件
    • https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
    • https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
    • https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
    • https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪一个属性排序,以及排序顺序
    • https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件
  • 状态码
    200 OK - [GET]:服务器成功返回用户请求的数据,该操做是幂等的(Idempotent)。
    201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
    202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
    204 NO CONTENT - [DELETE]:用户删除数据成功。
    400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操做,该操做是幂等的。
    401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
    403 Forbidden - [*] 表示用户获得受权(与401错误相对),可是访问是被禁止的。
    404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操做,该操做是幂等的。
    406 Not Acceptable - [GET]:用户请求的格式不可得(好比用户请求JSON格式,可是只有XML格式)。
    410 Gone -[GET]:用户请求的资源被永久删除,且不会再获得的。
    422 Unprocesable entity - [POST/PUT/PATCH] 当建立一个对象时,发生一个验证错误。
    500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将没法判断发出的请求是否成功。
    
    更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
  • 错误处理,应返回错误信息,error当作key。
    {
        error: "Invalid API key"
    }
  • 返回结果,针对不一样操做,服务器向用户返回的结果应该符合如下规范。
    GET /collection:返回资源对象的列表(数组)
    GET /collection/resource:返回单个资源对象
    POST /collection:返回新生成的资源对象
    PUT /collection/resource:返回完整的资源对象
    PATCH /collection/resource:返回完整的资源对象
    DELETE /collection/resource:返回一个空文档
  • Hypermedia API,RESTful API最好作到Hypermedia,即返回结果中提供连接,连向其余API方法,使得用户不查文档,也知道下一步应该作什么。
    {"link": {
      "rel":   "collection https://www.example.com/zoos",
      "href":  "https://api.example.com/zoos",
      "title": "List of zoos",
      "type":  "application/vnd.yourformat+json"
    }}

 补充知识:跨域

浏览器的同源策略限制了从同一个源加载的文档或脚本如何与来自另外一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。”

简单来讲就是:比如在一个浏览器上访问两个不一样的网站,这两个网站页面有本身的脚本,他们在访问请求服务器资源时,浏览器会检查它们属于哪一个网站或者说服务器,若是它跨服务器访问了,那么浏览器就拒绝这种请求

浏览器安全的基石是 同源策略,什么是同源策略呢?言简意赅,就是三个相同:

协议相同。
域名相同。
端口相同。
这三者相同的状况下,才被称做 “同源”,同源策略,能够保证你的服务器的接口是隐私的。

跨域的例子:

端口不一样:

假设,你的电脑如今有开启了两个服务器,分别在 不一样的端口

http://localhost:8080/index.html    // 发送 ajax 请求

http://localhost:3000    //         提供接口

在这里,这个服务器并无遵照 同源策略 了,此时,就产生了跨域问题。

协议不一样:

举一个很常见的例子,双击打开一个 html 文件,你会看到

file:///Users/xxx/Documents/index.html    // 客户端
同时在浏览器上你会看到: http://localhost:3000 // 服务器

这就是简单的 协议不一样 的跨域例子,这个例子,也是咱们最好实现的例子 。。。

域名不一样:

这个更明显了:

https://www.xxx.com/index.html    // 客户端

https://www.yyy.com        // 服务器

解决方案

1.安装django-cors-headers

pip3 install django-cors-headers

2.配置settings.py文件

INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
 ] 

MIDDLEWARE_CLASSES = (
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware', # 注意顺序
    ...
)
#跨域增长忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
    '*'
)

CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)

CORS_ALLOW_HEADERS = (
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
)

其余解决方案

1.使用JSONP

使用Ajax获取json数据时,存在跨域的限制。不过,在Web页面上调用js的script脚本文件时却不受跨域的影响,JSONP就是利用这个来实现跨域的传输。所以,咱们须要将Ajax调用中的dataType从JSON改成JSONP(相应的API也须要支持JSONP)格式。 
JSONP只能用于GET请求。

2.直接修改Django中的views.py文件

修改views.py中对应API的实现函数,容许其余域经过Ajax请求数据: 

def myview(_request): 
response = HttpResponse(json.dumps({“key”: “value”, “key2”: “value”})) 
response[“Access-Control-Allow-Origin”] = “*” 
response[“Access-Control-Allow-Methods”] = “POST, GET, OPTIONS” 
response[“Access-Control-Max-Age”] = “1000” 
response[“Access-Control-Allow-Headers”] = “*return response

5、基于原生django开发restful的接口

def books(request):
    # 获取全部图书
    if request.method=='GET':
        books=models.Book.objects.all()
        #把queryset对象转成json格式字符串
        # ll=[]
        # for book in books:
        #     bo={'name':book.name,'publish':book.publish}
        #     ll.append(bo)
        #列表推导式
        ll=[{'name':book.name,'publish':book.publish} for book in books]
        response={'code':100,'msg':'查询成功','data':ll}
        #safe=False 若是序列化的对象中有列表,须要设置
        return JsonResponse(response,safe=False,json_dumps_params={'ensure_ascii':False})

 6、drf安装、使用、APIView 的源码、equset的源码分析

DRF:Django REST framework

Django REST framework 框架是一个用于构建Web API 的强大而又灵活的工具。

一般简称为DRF框架 或 REST framework。

DRF框架是创建在Django框架基础之上,由Tom Christie大牛二次开发的开源项目。

特色

  • 提供了定义序列化器Serializer的方法,能够快速根据 Django ORM 或者其它库自动序列化/反序列化;
  • 提供了丰富的类视图、Mixin扩展类,简化视图的编写;
  • 丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,知足各类须要;
  • 多种身份认证和权限认证方式的支持;
  • 内置了限流系统;
  • 直观的 API web 界面;
  • 可扩展性,插件丰富

安装、使用

-pip3 install djangorestframework
-pycharm中安装
-第一步,再写视图,都写cbv
from rest_framework.views import  APIView
class Books(APIView):
    pass
-在setting中配置 INSTALLED_APPS= [ 。。。。。 'rest_framework' ]

 源码分析:

APIView

1视图类继承了APIView以后,全部的请求都被禁用了csrf认证:
2.在APIView中as_view本质上仍是调用了父类的as_view(View的as_view)

 3.as_view中调用dispatch,这个dispatch是APIView的dispatch

 

 APIView之dispatch方法:

-一、对原生的request对象作了一层包装(面向对象的封装),之后再用的request对象都是drf的新的request对象

-二、2 在APIView中self.initial(request, *args, **kwargs),里面有频率控制,权限控制和认证相关

-3 根据请求方法执行我们写的视图类中的相应方法
--视图类中方法的request对象,已经变成了封装后的request

 APIView之Request方法:

-1 原生的request是self._request

-2 取以post形式提交的数据,从request.data中取(urlencoded,formdata,json格式)

-3 query_params 就是原生request的GET的数据

-4 上传的文件是从FILES中取
-5 (重点)其余的属性,直接request.属性名(由于重写了__getattr__方法)

 

相关文章
相关标签/搜索