Django 学习视图之FBV与CBV

时间:2021-02-22 18:21:27

. CBVFBV

CBVClass Based View

FBVFunction Based View

我们之前写过的都是基于函数的view,就叫FBV。还可以把view写成基于类的,那就是CBV

下面我们就拿添加用户为例:

1.FBV版本

首先:urls.py 的与视图关系编写为:path('register/', views.register),

然后是视图函数的内容:

from django.contrib.auth.models import User

from django.shortcuts import render, HttpResponse, redirect

# 注册及验证 (前端模板是以ajax实现)

def register(request):

    if request.method == "GET":

        return render(request, "register.html")

    if request.method == "POST":

        username = request.POST.get("username")

        password = request.POST.get("pwd")

        print(username)

        print(password)

        User.objects.create_user(username=username, password=password)  # User是以个对象

        return redirect("/index/")

 

2.CBV版本

首先:urls.py 的与视图关系编写为:path('register/', views.Register.as_view()),

然后是视图函数类编写的内容:

from django.views import View

class Register(View):

    def get(self, request):

        return render(request, "register.html")

 

    def post(self, request):

        username = request.POST.get("username")

        password = request.POST.get("pwd")

        print(username)

        print(password)

        User.objects.create_user(username=username, password=password)  

# User是以个对象

        return redirect("/index/")

 

. 给视图加装饰器

1. 使用装饰器装饰FBV

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

# 一个时间的装饰器来验证是否运行了装饰器

def wrapper(func):

    def inner(*args, **kwargs):

        start_time = time.time()

        time.sleep(2)

        ret = func(*args, **kwargs)

        end_time = time.time()

        print("used:", end_time - start_time)

        return ret

 

return inner

 

 

@wrapper

def register(request):

    if request.method == "GET":

        return render(request, "register.html")

    if request.method == "POST":

        username = request.POST.get("username")

        password = request.POST.get("pwd")

        print(username)

        print(password)

        User.objects.create_user(username=username, password=password)  # User是以个对象

        return redirect("/index/")

 

访问的时候大概停留两秒再进行访问。并在后台打印出运行后的时间。

2.使用装饰器装饰CBV

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

使用之前需要先导入相应的包

from django.views import View

from django.utils.decorators import method_decorator

方式一:给某个方法加上装饰器(此例给get方法加上)

class Register(View):

    @method_decorator(wrapper)

    def get(self, request):

        return render(request, "register.html")

 

    def post(self, request):

        username = request.POST.get("username")

        password = request.POST.get("pwd")

        print(username)

        print(password)

        User.objects.create_user(username=username, password=password)  

# User是以个对象

        return redirect("/index/")

 

方式二:加在dispatch方法上面,会给类下的所有方法加上此装饰器

class Register(View):

    # 加在dispatch方法上面,会给类下的所有方法加上此装饰器

    @method_decorator(wrapper)

def dispatch(self, request, *args, **kwargs):

#这样的写法兼容python2*

        obj = super(Register, self).dispatch(request, *args, **kwargs)  

# python3写法如下(此方法不兼容python2*)

# obj = super().dispatch(request, *args, **kwargs)

        return obj

    def get(self, request):

        return render(request, "register.html")

 

    def post(self, request):

        username = request.POST.get("username")

        password = request.POST.get("pwd")

        print(username)

        print(password)

        User.objects.create_user(username=username, password=password)  

# User是以个对象

        return redirect("/index/")

 

此方式会给类下的所有方法加上此装饰器,也就是在这个注册过程运行了两次的装饰器,一次GET方法访问网页,一次POST方法注册。

 

方式三:加在类上面

@method_decorator(wrapper, name="post")

@method_decorator(wrapper, name="get")  # 给哪个方法加,就要指定name

class Register(View):

 

    def get(self, request):

        return render(request, "register.html")

 

    def post(self, request):

        username = request.POST.get("username")

        password = request.POST.get("pwd")

        print(username)

        print(password)

        User.objects.create_user(username=username, password=password)  # User是以个对象

        return redirect("/index/")

 

上面加装饰器的方法是有固定格式的:

@method_decorator(装饰器名, name="类中需要装饰器的函数")

可以从源码中看出格式固定如截图:

Django 学习视图之FBV与CBV

补充:

以上的例子均可以使用下面的前端模板register.html

Django 学习视图之FBV与CBVDjango 学习视图之FBV与CBV
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 新 Bootstrap 核心 CSS 文件 -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>

<div class="container">
    <div class="row con">

        <form action="" method="post">
            {% csrf_token %}
            <div class="form-group col-sm-4 col-sm-offset-4">
                <h2>注册用户</h2>
                <label for="exampleInputEmail1">用户名</label>
                <input type="text" class="form-control" id="exampleInputEmail1" placeholder="用户名" name="username">
            </div>
            <div class="form-group col-sm-4 col-sm-offset-4">
                <label for="exampleInputPassword1">密码</label>
                <input type="password" class="form-control" id="exampleInputPassword1" placeholder="密码" name="pwd">
            </div>
            <div class="form-group col-sm-6 col-sm-offset-3">
                <button type="submit" class="btn btn-default col-sm-offset-2">确认</button>
                <button type="submit" class="btn btn-default col-sm-offset-2">返回</button>

            </div>

        </form>

    </div>
</div>
</body>
</html>
register.html