Django之cbv分析、restful、drf框架部分源码分析

一、django的请求生命周期

Django之cbv分析、restful、drf框架部分源码分析_第1张图片

具体步骤如下: 

  1. 用户通过浏览器访问服务器
  2. 首先进入实现了WSGI协议的web服务器
  3. 进入django的中间件
  4. 开始路由匹配
  5. 执行相应的视图函数
  6. 取模板,取数据,用数据渲染模板
  7. 返回模板的字符串
  8. 数据展示到用户浏览器

Django之cbv分析、restful、drf框架部分源码分析_第2张图片

二、开发模式

1、前后端不分离项目

  • 前端页面看到的效果都是由后端渲染页面或重定向
  • 前端与后端的耦合度很高

2、前后端分离项目

  • 前端和后端独立开发
  • 通过json格式进行数据交互
  • 后端仅返回前端所需的数据,不再渲染HTML页面,不再控制前端的效果
  • 前端与后端的耦合度相对较低

三、CBV源码分析

视图函数一般有两种:

  1. CBV:基于类的视图
  2. FBV:基于函数的视图

 CBV的执行流程:

路由如果这么配置:url(r'^test/', views.Test.as_view()),
        请求通过中间件后进入路由--->根据路由匹配,一旦成功,会执行后面函数(request)--->本质就是执行了as_view内部的view函数---->内部又调用了self.dispatch方法---->根据请求方式,执行不同的方法(比如get请求,就会执行咱们写的视图类的get方法)

具体可参考我这篇的源码分析:https://blog.csdn.net/weixin_40406241/article/details/91385702

无论是什么请求方式,都需要经过dispatch()方法,那么我们在中间件做控制的操作就可以直接将dispatch()方法重写来实现。比如访问频率的控制等 。

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^Test/', views.Test.as_view())
]
from django.shortcuts import render, HttpResponse, redirect
from django.views import View


class APIView(View):
    def dispatch(self, request, *args, **kwargs):
        # 前面写一些频率控制的东西
        res = super().dispatch(request, *args, **kwargs)
        return res


class Test(APIView):
    # http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    def get(self, request, *args, **kwargs):
        return HttpResponse('ok')

四、restful规范

restful是个什么鬼?

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

restful    API设计规范

  • API与用户的通信协议,总是使用HTTPs协议。
  • 域名有区分:

           https://api.example.com                         尽量将API部署在专用域名(会存在跨域问题)

           https://example.org/api/                        API很简单

  • 版本:

          可以放在路径中,如:https://api.example.com/v1/

          也可以放在请求头中

  • 路径,视网络上任何东西都是资源,均使用名词表示(重点)

          https://api.example.com/v1/zoos

          https://api.example.com/v1/books

  • 通过method区分是什么操作

          -get表示获取
          -post表示新增
          -delete表示删除
          -patch/put 表示修改

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

          https://api.example.com/v1/zoos?limit=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:指定筛选条件

  • 状态码:{"status_code": 100}
  • 错误处理,应返回错误信息,error当做key

          {"status_code":100,'msg':'登录成功'}
          {"status_code":101,'msg':'用户名错误'}

  • 返回结果,针对不同操作,服务器向用户返回的结果

          -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,....}}

          -新增数据,把新增的数据再返回
          -修改了数据,返回完整的资源对象
          -删除数据,返回一个空文档

  • 返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。

参考自:https://www.cnblogs.com/liuqingzheng/articles/9762022.html

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

models.py:

from django.db import models

class Book(models.Model):
    id=models.AutoField(primary_key=True)
    name=models.CharField(max_length=32)
    publish=models.CharField(max_length=32)

视图函数:

from django.http import JsonResponse
from app01 import models

def books(request):
    # 获取所有图书
    if request.method == 'POST':
        books = models.Book.objects.all()
        # 前后端分离,需要把queryset对象转成json格式返回
        '''
        ls = []
        for book in books:
            bo = {'name': book.name, 'publish': book.publish}
            ls.append(bo)
        '''
        # 上面的for循环换成列表推导式
        ls = [{'name': book.name, 'publish': book.publish} for book in books]
        response = {'code': 100, 'msg': '查询成功', 'data': ls}
        # safe=False,如果json序列化的对象中有列表,需要设置
        return JsonResponse(response, safe=False, json_dumps_params={'ensure_ascii': False})

六、djangorestframework

安装:

pip3 install djangorestframework

或者pycharm直接安装

 使用了drf框架后,以后的视图都要写成CBV。

使用时,需要在settings的app注册里注册:

INSTALLED_APPS= [
        ……
    'rest_framework'
]

往之前的表里插入两条数据:

Django之cbv分析、restful、drf框架部分源码分析_第3张图片

先来写一个符合规范的简单get请求 :

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^books/', views.Books.as_view()),
]

视图函数:

from rest_framework.views import APIView
from django.http import JsonResponse
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.query_params  是原来django原生的GET中的数据;
        request.FILES  就是上传的文件.
        '''
        books = models.Book.objects.all()
        ls = [{'b_name': book.name, 'publish': book.publish} for book in books]
        dic = {'name': 'shj', 'age': 18, 'girl_friend': ['刘亦菲', '李一桐', '其他女友'], 'book': ls}
        return JsonResponse(dic, safe=False, json_dumps_params={'ensure_ascii': False})

浏览器访问拿到的数据如下: 

{"name": "shj", "age": 18, "girl_friend": ["刘亦菲", "李一桐", "其他女友"], "book": [{"b_name": "剑来", "publish": "北京出版社"}, {"b_name": "雪中悍刀行", "publish": "上海出版社"}]} 

drf视图函数request使用总结: 

  • request是被封装后的request,原生的request在request._request;
  • 如果想用原生requset中的属性,还是原来的用法,因为Request重写了__getattr__方法;
  • 原生django只能处理urlencoded和formdata编码,如果是json格式,原生django是不能处理的,需要自己从body中取出来自行处理;
  • request.data 不管前端传数据的编码格式是urlencoded,formdata或者是json,都从里面取值;
  • request.query_params  是原来django原生的GET中的数据;
  • request.FILES  就是上传的文件.

源码分析:

APIView实际上继承了django的View

在CBV继承了APIView之后:

1 所有的请求都没有csrf的认证了
2 在APIView中as_view本质还是调用了父类的as_view(View的as_view)
3 as_view中调用dispatch  -----> 这个dispatch是APIView的dispatch

Django之cbv分析、restful、drf框架部分源码分析_第4张图片

 调用父类的as_view(),执行时,又要调用dispatch()方法,这时候,父类View有dispatch方法,APIView类也有dispatch方法,那么执行谁的呢?这就与属性查找顺序有关了。我们继承了APIView,APIView继承了View,那么查找的时候应该先找自己的,因为我们没有写,那么就找它的上一级父类,也就是APIView,这时候发现APIView对dispatch方法是重写了的,因此,接下来走的就是APIView的dispatch方法。

 Django之cbv分析、restful、drf框架部分源码分析_第5张图片

我们去 initialize_request中看看它到底对request做了什么。

 Django之cbv分析、restful、drf框架部分源码分析_第6张图片

点进去看一看 

Django之cbv分析、restful、drf框架部分源码分析_第7张图片

 再回到initialize_request,可以知道Request()对象已经是封装后的新的request。

再去dispatch中

 Django之cbv分析、restful、drf框架部分源码分析_第8张图片

 Django之cbv分析、restful、drf框架部分源码分析_第9张图片

Django之cbv分析、restful、drf框架部分源码分析_第10张图片

你可能感兴趣的:(Django框架)