Django的视图

3.1 认识视图函数

Django中的视图是MTV模式中的View层,用于处理客户端的请求并生成响应数据。在视图中使用函数处理请求的方式,被称为视图函数,也叫作FBV(Function Base Views)。视图函数的代码一般放在应用目录下的views.py文件中。

3.1.1 什么是视图函数

先来看一个简单的视图函数——返回字符串的视图函数:
这里我们用应用app1下的views.py,增加视图函数hello()。代码如下所示:

from django.http import HttpResponse # 这行代码拉出来解释
def hello(request):
    return HttpResponse("hello,this is a test page")

首先,从django.http模块中导入了HttpResponse类。接着,定义视图函数hello()。视图函数默认接受一个HttpRequest对象作为第一个参数,通常定义一个变量request来接受这个参数数据。
视图函数hello()会返回一个HttpResponse对象,其中包含生成的相应数据。

3.1.2 视图函数的底层原理

视图函数主要使用HttpRequest对象(请求对象)和HttpResponse对象(相应对象)。当浏览器向服务端请求一个页面的时候,Django先创建一个HttpRequest对象(该对象中包含请求的元数据)然后加载相应的视图,将这个HttpRequest对象作为第1个参数传递给视图函数。视图函数会返回一个HttpResponse对象。

  • 1.HttpRequest对象
    HttpRequest对象主要包含以下的属性/方法:
属性/方法含义
path字符串,表示请求页面的路径,不包含域名
method字符串,表示页面的请求方法,常用值包括"GET"和"POST"。必须使用大写
encoding字符串,表示提交数据的编码方式。一般默认为UTF-8编码
GET字典类型,包含GET请求方法中的所有参数
POST字典类型,包含POST请求方法中的所有参数
FILES字典类型,包含文件上传的信息
COOKIES字典类型,包含所有的Cookies对象
session字典类型,表示当前对话
META字典类型,包含所有的HTTP头部信息,如HTTP_USER_AGENT(客户端Agent信息)、REMOTE_ADDR(客户端的IP地址)
user表示当前登录的用户

下面通过一段代码演示HttpRequest对象的用法。
(1)定位到"app1/view.py",增加视图函数test_get(),如下所示:

def test_get(request):
    print(request.get_host()) # 域名 + 端口
    print(request.path) # 获取访问文件路径,不含参数
    print(request.get_full_path()) # 获取访问文件路径,包含参数
    print(request.method) # 获取请求中使用的HTTP方式(POST/GET)
    print(request.GET) # 获取get请求数据
    print(request.META["HTTP_USER_AGENT"]) # 用户浏览器的user-agent字符串
    print(request.META["HTTP_X_REAL_IP"]) # 用户浏览器的ip地址
    print(request.META["REMOTE_ADDR"]) # 客户端ip地址
    print(request.GET.get('username')) # 获取get参数
    
    return HttpResponse("")

在"app1/urls.py"配置路由如下:

path('app1/test_get/',views.test_get),

运行项目,控制台的输出如下:
请添加图片描述

(2)定位到"app1/view.py",增加视图函数test_post(),如下所示:

def test_post(request):
    print(request.method) # 获取请求中使用的HTTP方式(POST/GET)
    print(request.POST.get('username')) # 获取post请求数据
    
    return render(request,"2/test_post.html")

新建文件"templates/2/test_post.html",添加如下代码:

<form method="POST">
    {% csrf_token %} 
    <input type="text" name="username"> 
    <input type="submit" value="提交参数">
</form>

配置路由如下:

    path('app1/test_post/',views.test_post), # 测试test_post请求

运行后,控制台输出如下:

在这里提交参数,就可以在控制台看到结果。
请添加图片描述
请添加图片描述

  • 2.HttpResponse对象
    每个视图函数都会返回一个HttpResponse对象,该对象包含返回给客户端的所有数据。
    HttpResponse对象的常用属性如下:
属性含义
content返回的内容
status_code返回的HTTP响应状态码
content-type返回的数据的MIME类型,默认为text/html

常用的状态码status_code如下:

状态码含义
200响应成功
301永久重定向,Location属性的值为当前的URL
302临时重定向,Location属性的值为新的URL
404URL不存在
403未授权访问
500内部服务器报错
502网关错误
503服务不可用

下面通过一段代码演示HttpResponse对象的用法:
(1)定位"app1/views.py",增加视图函数test_response(),如下代码:

def test_response(request):
    response = HttpResponse()
    response.write("这里是Response测试页面")
    response.write("<br>")
    response.write(response.content) # 响应可以指定以内容的形式返回
    response.write("<br>")
    response.write(response["content-type"]) # 返回数据的数据类型
    response.write("<br>")
    response.write(response.status_code) # 返回数据的状态码
    response.write("<br>")
    response.write(response.charset) # 返回数据的编码
    response.write("<br>")
    
    return response

定位到"app1/urls.py",增加一条路由规则,如下所示:

	path('app1/test_response/',views.test_response), # 测试response请求

启动项目,访问:http://127.0.0.1:8000/app1/test_response/
请添加图片描述

3.1.3 视图处理函数的使用

通过HttpRequest对象和HttpResponse对象,可以处理基本的数据请求并返回相应数据。但是这种方式较为繁琐,Django将这些底层的操作过程全部进行了封装,提供了几个简单的函数供我们使用,这里展开来说:

  • 1.用render()函数实现页面渲染
    render()函数,根据模板文件和传递给模板文件的字典类型的变量,生成一个HttpResponse对象并返回。
    render()函数的格式为:
from django.shortcuts import render
render(request,template_name,content=None,content_type=None,status=None,using=None)

参数含义如下:

参数含义
request传递给视图函数的所有请求,其实就是视图函数的参数request
template_name渲染的模板文件,一般放在templates目录下面
content数据格式为字典类型,保存要传递到HTML文件中的变量
content_type用于生成文档的MIME类型。默认为text/html
status表示响应的状态码,默认为200
using设置模板引擎,用于解析模板文件

下面通过代码向test_render.html文件传递变量名为“info”、值为“Django测试页面”的字典变量,并设置返回给浏览器的类型为text/html。
(1)定位到"app1/views.py"增加视图函数test_render(),如下所示:

def test_render(request):
    return render(request,"2/test_render.html",{'info':'这里是render测试页面'},content_type="text/html")

(2)新建"templates/2/test_render.html"文件,写入以下代码:

<div>
    接收变量
    <br>
    {{info}}
</div>

(3)定位到"app1/urls.py"增加路由,如下所示:

    path('app1/test_render/',views.test_render), # 测试render()函数

请添加图片描述

  • 2.用redirect()函数实现页面重定向
    在项目开发过程中,经常会遇到网页重定向的情况。如遇到网站的目录结果被调整了、网页被移动到一个新地址这类情况,若不做重定向,则通过用户收藏夹中的链接或者搜索引擎数据库中的旧地址只能得到一个404的页面返回。
    在Django中,常用重定向函数redirect()函数实现网页重定向。该函数的参数包含以下3种情况:

(1)通过调用模型的get_absolute_url()函数进行重定向
定位到"app1/models.py",写入以下代码:

from django.db import models
from django.urls import reverse

class UserBaseInfo(models.Model):
    id = models.AutoField(verbose_name = '编号',primary_key=True) # id字段主键
    user_name = models.CharField(verbose_name = '姓名',max_length=30) # 姓名字段
    user_password = models.CharField(verbose_name = '密码',max_length=32) # 密码字段
    status = models.BooleanField(verbose_name = '状态',max_length=1) # 状态
    createdate = models.DateTimeField(verbose_name = '创建时间',auto_now_add=True,db_column='createDate') # 创建时间

    def __str__(self):
        return str(self.id) # 为自定义的字段显示内容
        
    def get_absolute_url(self):
        return reverse("app1_userinfo", kwargs={"id":self.pk}) 
    
    class Meta:
        verbose_name = '用户信息'
        db_table = 'UserBaseInfo2'

在上述代码中,定义了get_absolute_url()方法,用于返回模型对外的URL;使用reverse()函数做反向解析操作。

在执行命令前,要开启本地/远程数据库,配置好连接数据库的操作(LAMP/phpstudy)
请添加图片描述
请添加图片描述

执行数据库迁移操作,命令如下:

$ python3 manage.py makemigrations
$ python3 manage.py migrate

此时终端显示如下,并会在数据库中自动生成对应的表:
请添加图片描述
请添加图片描述

定位到"app1/views.py",增加视图函数test_redirect_model()及userinfo():

from .models import * # 在最上面引入models中的所有方法
from django.shortcuts import render,redirect # 这里补上redirect

def test_redirect_model(request,id): # 使用redirect 函数来跳转到指定模型
    user = UserBaseInfo.objects.get(id=id) # 从模型中获取对象
    return redirect(user) # 使用redirect函数跳转到指定模型

def userinfo(request,id):
    user = UserBaseInfo.objects.get(id=id)
    return HttpResponse("编号:"+str(user.id)+"姓名:"+user.user_name)

定位到"app1/urls.py"增加如下路由规则:

    path('app1/test_redirect_model/<int:id>/',views.test_redirect_model,name="app1_test_redirect_model"),
    path('app1/userinfo/<int:id>/',views.userinfo,name="app1_userinfo"),

同时去settings.py中将app1注册:
请添加图片描述
这里,不论我们访问test_redirect_model路由还是userinfo路由,结果都如下,这是由于test_redirect_model路由发生了302重定向,跳转到了userinfo路由。
请添加图片描述
请添加图片描述

执行过程如下:
1.在视图函数test_redirect_model()时,redirect()函数包含一个模型实例
2.调用该模型实例的get_absolute_url()方法。
3.而get_absolute_url()方法通过reverse()函数做反向解析,组装出"app1/userinfo/1"这样的路由规则;然后根据这个路由规则,找到对应的视图函数userinfo(),执行并得到结果。

(2)通过路由反向解析进行重定向
定位到"app1/views.py",增加视图函数test_redirect_views(),如以下代码:

def test_redirect_views(request,id):
    return redirect('app1_userinfo',id=id)

使用redirect()函数直接反向解析路由的效果,和使用reverse()函数的效果是一样的。定位到"app1/urls.py"增加下面的路由:

path('app1/test_redirect_views/<int:id>/',views.test_redirect_views,name="app1_test_redirect_views"),

请添加图片描述
(3)通过一个绝对的或相对的URL,让浏览器跳转到指定的URL进行重定向
定位到"app1/views.py"增加视图函数test_redirect(),写入代码:

def test_redirect(request):
    return redirect('https://www.baidu.com')

定位到"app1/urls.py",增加如下路由:

path('app1/test_redirect',views.test_redirect,name="app1_test_redirect"),

运行访问,就可以看到页面已经被重定向到百度了。

3.2 认识视图类

Django框架还提供了另外一种处理用户请求的方式——视图类的处理方式,它可以更好的处理不同的HTTP请求。

3.2.1 什么是视图类

在视图里使用类处理方式,被称为视图类(class base views CBV)。视图类可以更好地处理不同的HTTP请求。采用面向对象的思维,把每个方法的处理逻辑变成视图类中的单个方法,这样可以使程序的逻辑变得更加简单。
在处理视图逻辑时,不用通过"if…else…"这样的代码来区别请求方法是GET请求还是POST请求,而是通过视图类中定义get()方法和post()方法来进行区别。

3.2.2 对比视图函数和视图类

当用户请求某个路由地址,既有GET请求,也有POST 请求。对于这种情况,视图函数的定义如下:

def index_page(request):
	if request.method == 'GET';
	   return HttpResponse("GET请求")
	elif request.method == 'POST'
	   return HttpResponse("POST请求")

视图函数的定义有些繁琐且代码冗长。这里写一个视图类来做个对比:

from django.views import View
class IndexPageView(View):
	'''
	类视图
	'''
	def get(self, request):
		return HttpResponse("GET请求")
	def post(self, request):
		return HttpResponse("POST请求")

其中,视图类IndexPageView继承django.views模块下的View类,而View类需要从django.views模块中导入。
视图类的路由定义方式如下:

from app1.views import IndexPageView

urlpatterns = [
	path('indexpage/',IndexPageView.as_view())
]

视图类在调用的时候,只能是函数的方式,而不能是类的方式,因此,需要将视图类用as_view()转化为视图函数。

3.3.3 利用视图类进行功能设计

Django提供了众多视图类,通过视图类可以简化开发过程,这里介绍常用的视图类。

  1. 通用视图类——TemplateView
    TemplateView是一个通用视图类,用来渲染指定的模板。下面通过实例来了解其用法。为了和视图函数分开,我们这里新建一个"app1/views_class.py",增加视图类TestTemplateView,如以下代码所示:
from django.shortcuts import render,redirect
from django.http import HttpResponse
from django.views.generic import TemplateView # 导入TemplateView类

class TestTemplateView(TemplateView): 
    # 设置模板文件名称
    template_name = '2/test_templateview.html'
    # 重写父类的get_context_data()方法
    def get_context_data(self, **kwargs):
        # 这行代码表示从父类中获取context_data
        # **kwargs表示可变参数,可以传入任何参数,用于获取更多的上下文信息。
        context = super().get_context_data(**kwargs)
        # 增加模板变量info
        context['info'] = '该变量可以传递到模板'
        return context
  1. 首先导入TemplateView类。
  2. 通过继承TemplateView类的方式创建一个TestTemplateView类。
  3. 在TestTemplateView类中设置模板文件。
  4. 重写父类的get_context_data()方法获取新增的额外的变量。
  5. 在context字段中加入info变量,就可以在模板中通过{{info}}得到传递的字典变量了。
    路由配置如下(app1/urls.py):
from app1.views_class import * # 导入views_class中的所有
	
	...
    path('app1/test_templateview',TestTemplateViews.as_view()),
  1. 列表视图类——ListView
    ListView视图类用于将数据表中数据以列表的方式显示。
    (1)定位到"app1/views_class.py",增加视图类TestListView,如以下代码:
from django.views.generic import TemplateView,ListView # 导入ListView类
from .models import *

class TestListView(ListView):
    model = UserBaseInfo
    template_name = '2/test_listview.html'
    # 设置模板变量的上下文
    context_object_name = 'users' # 模板变量名称为users
    # 设置每页显示的数据条数
    paginate_by = 2
    # queryset=UserBaseInfo.objects.filter(status=1)
    # 重写父类的get_queryset()方法
    def get_queryset(self):
        # 返回状态为1的数据
        userinfo = UserBaseInfo.objects.filter(status=1)
        return userinfo
    # 重写父类的get_context_data()方法
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 增加模板变量info
        context["info"] = "ListView变量可以传递到模板"
        print(context)
        return context
  1. 首先导入ListView类。
  2. 通过继承ListView类的方式创建一个TestListView类。
  3. 在TestListView类中需要设置模板文件。
  4. 通过重写父类get_queryset()方法获取属性queryset的值。
  5. 通过重写父类get_context_data()方法来获取新增的额外变量
  6. 在context字段中加入了info变量,在模板中通过{{info}}得到传递的字典变量。

如果没有设置context_object_name,则在模板变量上下文由“模型名称的小写+_list”组成。

(2)新建文件“templates/2/test_listview.html”,在其中添加如下代码:

<div>
    接收变量
    <br>
    {{info}}
    <table border=1>
        {% for user in users %}
        <tr>
            <td>{{ user.user_name }}</td>
            <td>{{ user.status}}</td>
            <td>{{ user.createdate }}</td>
        </tr>
        {% endfor %}
    </table>
    <table>
        <tr>
            {% if page_obj.has_previous %}
            <td>
                <a herf="?page={{ page_obj.previous_page_number }}">
                    上一页
                </a>
            </td>
            {% endif %}
            {% if page_obj.has_next %}
            <td>
                <a herf="?page={{ page_obj.next_page_number }}">
                    下一页
                </a>
            </td>
            {% endif %}
        </tr>
    </table>
</div>![请添加图片描述](https://img-blog.csdnimg.cn/74232737b2d642839be6244f9c711b29.png)

其中page_obj为分页对象,在ListView类中属于固定的用法。
(3)配置路由并访问页面,结果如图:
请添加图片描述
通过控制台也可以看到content变量:
请添加图片描述
3. 详细视图类——DetailView
DetailView视图类用于将数据表的数据以详细视图的形式显示。
(1)定位到"app1/views_class.py",增加视图类TestDetailView,如下:

from django.views.generic import TemplateView,ListView,DetailView 

class TestDetailView(DetailView):
    model = UserBaseInfo
    template_name = '2/test_detailview.html'
    # 设置模板变量
    context_object_name = "users"
         # 模板变量名称为userid
    pk_url_kwarg = "userid"
  1. 首先,导入DetailView。
  2. 继承DetailView类的方式创建一个类TestDetailView,在类TestDetailView中需要设置模板文件。pk_url_kwarg代表由地址中的某个参数,该参数用于记录的主键字段的值。
    (2)新建文件"test_detailview.html",写入下面的代码:
<div>
    <table border="1">
        <tr>
            <td>姓名:</td>
            <td>{{ users.user_name }}</td>
        </tr>
        <tr>
            <td>注册时间:</td>
            <td>{{ users.createdate }}</td>
        </tr>
    </table>
</div>

(3)配置路由并访问页面,结果如下:

    path('app1/test_detailview/<int:userid>/',TestDetailView.as_view()),

请添加图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

如此李想

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值