django中的逻辑处理主要是在视图(views)中完成,而视图分为两类:函数视图(FBV)和类视图(CBV)。

视图

一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。

响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。

放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。

下面是一个以 HTML 文档的形式返回当前日期和时间的视图:

1
2
3
4
5
6
7
from django.http import HttpResponse
import datetime

def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)

让我们来逐行解释下上面的代码:

首先,我们从 django.http模块导入了HttpResponse类,以及Python的datetime库。

接着,我们定义了current_datetime函数。它就是视图函数。每个视图函数都使用HttpRequest对象作为第一个参数,并且通常称之为request

注意,视图函数的名称并不重要;不需要用一个统一的命名方式来命名,以便让Django识别它。
我们将其命名为current_datetime,是因为这个名称能够比较准确地反映出它实现的功能。

这个视图会返回一个HttpResponse对象,其中包含生成的响应。

Django使用请求和响应对象来通过系统传递状态。

当浏览器向服务端请求一个页面时,Django创建一个HttpRequest对象,该对象包含关于请求的元数据。然后,Django加载相应的视图,将这个HttpRequest对象作为第一个参数传递给视图函数。

每个视图负责返回一个HttpResponse对象。

FBV

基本用法

  • function based view 基于函数的视图
1
2
3
4
5
6
7
from django.shortcuts import HttpResponse
import datetime


def mul(request):
now = datetime.datetime.now()
return HttpResponse(now)
  • 路由映射
1
2
3
4
5
6
7
from django.conf.urls import path
from app01 import views


urlpatterns = [
upathrl(r'mul/', views.mul),
]

装饰器

FBV 本身就是一个函数,所以和给普通的函数加装饰器无差:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from django.shortcuts import HttpResponse
import time


def wrapper(func):
def inner(*args, **kwargs):
start_time = time.time()
ret = func(*args, **kwargs)
end_time = time.time()
print("used:", end_time-start_time)
return ret
return inner


# FBV版添加装饰器
@wrapper
def add_class(request):
now = datetime.datetime.now()
return HttpResponse(now)

扩充

如果客户端直接向服务器提交post请求,没有携带csrf_token参数,就会出现403,禁止提交。

如果想要绕过csrf验证,有两种选择,一种就是,直接关闭中间件;另一种,就是在视图中,使用csrf装饰器跳过验证。

1
2
3
4
5
6
7
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import HttpResponse

@csrf_exempt
def test(request):
name = request.POST.get("name")
return HttpResponse(name)

CBV

基本用法

  • class based view 基于类的视图
1
2
3
4
5
6
7
8
9
10
11
12
13
from django.views import View
from django.shortcuts import HttpResponse


# 处理不同请求方式的逻辑清晰明了
class AddPublisher(View):
def get(self,request):
"""处理get请求"""
return HttpResponse("GET 请求")

def post(self,request):
"""处理post请求"""
return HttpResponse("POST 请求")
  • 路由映射
1
2
3
4
5
6
7
#urls.py 文件
from django.conf.urls import path
from app01 import views

urlpatterns = [
path(r'add_publisher/', views.AddPublisher.as_view()),
] # 固定写法注意.as_view()是要加括号的

执行流程

CBV 如何获取页面请求类型, 并响应的

  1. 项目启动,执行AddPublisher.as_view() ——> view

    1
    path('add_publisher/',views.AddPublisher.as_view())
  2. 请求到来时执行view函数:

    1. 实例化AddPublisher ——》 self

    2. self.request = reqeust

    3. 执行self.dispatch(request,*args,**kwargs)

      1. 判断请求方式是否被允许 http_method_names = []

        1. 允许:通过反射获取到当前请求方式对应的方法 ——> handler

        2. 不允许:self.http_method_not_allowed ——> handler

      2. 执行handler(request,*args,**kwargs) ——> 返回响应

装饰器

  • 类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。
  • Django 中提供了 method_decorator 装饰器用于将函数装饰器转换为方法装饰器。

装饰器加在类方法上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import time
from django.views import View
from django.utils.decorators import method_decorator #导入method_decorator装饰器

def timer(func):
def inner(request, *args, **kwargs):
start = time.time()
ret = func(request, *args, **kwargs)
print("函数执行的时间是{}".format(time.time() - start))
return ret
return inner

class AddClass(View):

@method_decorator(timer) # 将函数装饰器转换为方法装饰器
def get(self,request):
"""处理get请求"""
return HttpResponse("GET 请求")

def post(self,request):
"""处理post请求"""
return HttpResponse("POST 请求")

dispatch() 加装饰器

使用CBV时要注意,请求过来后会先执行dispatch()这个方法,如果需要对该视图类的所有请求方法做批量处理,就可以在dispatch()方法上加装饰器,在所有的请求方法中都生效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import time
from django.views import View
from django.utils.decorators import method_decorator #导入方法装饰器

def timer(func):
def inner(request, *args, **kwargs):
start = time.time()
ret = func(request, *args, **kwargs)
print("函数执行的时间是{}".format(time.time() - start))
return ret
return inner

class Login(View):

@method_decorator(timer) #相当于给get,post请求都加上了装饰器
def dispatch(self, request, *args, **kwargs):
obj = super(Login,self).dispatch(request, *args, **kwargs)
return obj

def get(self,request):
"""处理get请求"""
return HttpResponse("GET 请求")

def post(self,request):
"""处理post请求"""
return HttpResponse("POST 请求")

装饰器加在类上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time
from django.views import View
from django.utils.decorators import method_decorator

def timer(func):
def inner(request, *args, **kwargs):
start = time.time()
ret = func(request, *args, **kwargs)
print("函数执行的时间是{}".format(time.time() - start))
return ret
return inner

@method_decorator(timer,name = 'get') # 相当于给get请求,加上了装饰器
@method_decorator(timer,name = 'post') # 相当于给post请求,加上了装饰器
class Login(View):

def get(self,request):
"""处理get请求"""
return HttpResponse("GET 请求")

def post(self,request):
"""处理post请求"""
return HttpResponse("POST 请求")