• Django(7):视图处理函数


    视图处理组件是路由的后置服务模块,主要有两种实现视图处理的模式:函数式编程和面向对象编程。本节主要讲面向函数式编程实现。

    视图处理函数的声明和规范

    视图处理函数主要咋views.py模块中,本身就是一个python‘函数,能够接受web请求,并返回web响应数据。

    1.视图处理函数的定义

    从前面章节中,就定义过视图函数,这里以前面我们说的公共模块为例,在文件personal_blog/common/views.py下定义函数如下:

    from django.http import HttpResponse
    
    
    def index(request):
        content = '

    hello views!

    '
    return HttpResponse(content)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    每个视图处理函数默认都接受一个HttpRequest参数,通常是用一个request接受。最后函数返回一个HttpResponse响应数据。

    2.定义URL路由

    定义好视图函数后,就不要和路关联。如下,修改子路由的common/urls.py,代码如下:

    from django.urls import path, re_path
    from . import views
    
    # 路由模块名称
    app_name = 'common'
    
    # 添加路由配置
    urlpatterns = [
        path('', views.index, name='index'),
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.常见错误处理

    django中,视图处理函数可以根据不同的错误直接返回指定的错误页面,对应HTTP规范中则会有各种错误码分别用于表示不同的错误信息。重构视图函数如下:

    def index(request):
    	# 数据处理过程
        # 自定义错误
        if flag == 'OK':
            content = '

    hello views!

    '
    return HttpResponse(content) elif flag == 'NOT FOUND': return HttpResponseNotFound('

    404错误,要访问的页面不存在

    '
    ) elif flag == 'NOT DENIED': return HttpResponseNotAllowed('

    405错误,访问失败

    '
    ) elif flag == 'FORBIDDEN': return HttpResponseForbidden('

    403错误,没有权限访问该页面

    '
    ) elif flag == 'SERVERERROR': return HttpResponseServerError('

    500错误,服务器内部出现错误

    '
    )
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    对于404,django框架内置了django.http.Http404错误类型,可以直接展示自定义的HTML错误信息,如下:

    def index(request):
     	# 404错误页面
        try:
            # 数据处理过程
            content = '

    hello views!

    '
    except: raise Http404('page not found!') return HttpResponse(content)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4.自定义错误视图

    可以参考上一节的内容。

    数据响应的快捷方式

    Django封装了一些快捷处理函数,如下:

    1. render():请求转发,在响应数据中可以使用请求对象。
    2. redirect():请求重定向。
    3. get_object_or_404():查询指定数据,如果数据不存在,直接返回404错误。
    4. get_list_or_404():查询指定类型的多条数据,如果数据不存在,直接返回404错误。
    5. render_to_response():请求转发,在响应数据中不能使用请求对象(最新版已移除此函数)。

    1.render

    render(
        request, template_name, context=None, content_type=None, status=None, using=None
    )
    
    • 1
    • 2
    • 3

    参数:

    • request:请求对象
    • template_name:HTML网页模板路径
    • context:响应上下文
    • content_type:响应数据类型
    • status:状态码
    • using:使用的引擎

    示例:重构首页index的视图处理函数,首先在项目根目录下的html_file文件下,创建首页文件index.html,如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>博客首页</title>
    </head>
    <body>
        <h1>博客首页</h1>
        {{ message }}
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    然后修改公共模块的视图处理函数,代码如下:

    from django.shortcuts import render
    
    
    def index(request):
        return render(request, 'index.html', {'message': "欢迎访问博客"})
    
    • 1
    • 2
    • 3
    • 4
    • 5

    render的底层同样是使用HttpResponse实现,源代码如下:

    from django.template import loader
    
    
    def render(
        request, template_name, context=None, content_type=None, status=None, using=None
    ):
        """
        Return an HttpResponse whose content is filled with the result of calling
        django.template.loader.render_to_string() with the passed arguments.
        """
        content = loader.render_to_string(template_name, context, request, using=using)
        return HttpResponse(content, content_type, status)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    底层通过loader加载器加载并渲染template_name路径指向的文件,然后把文件数据封装到HttpResponse中并返回。

    2.redirect

    redirect(to, *args, permanent=False, **kwargs)
    
    • 1

    参数:

    1. to:重定向的URL请求地址
    2. permanent:是否永久重定向(默认False)。

    基本操作方式有3中:

    1.通过数据模型的get_absolute_url()重定向。

    以前面博客项目的文章数据模型为例,在文章模型汇总定义如下函数:

    from django.db import models
    from django.urls import reverse
    
    
    class Article(models.Model):
       ...
        
        def get_absolute_url(self):
            return reverse('article:article_detail', kwargs={'article_id': self.id})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    然后在视图处理函数再,就可以直接通过对象返回了。如下,重构根据编号查询文章的视图处理函数:

    def article_detail(request, article_id):
        """查询指定编号的文章,article_id变量会接受路由中传递的数据"""
        print("查询指定编号的文章,编号:%s" % article_id)
        article = Article.objects.get(pk=article_id)
        return redirect(article)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.通过路由反向解析返回具体的事务页面。

    如下,可以通过redirect直接反向解析路由地址,功能和reverse一样:

    def article_publish(request):
        """发表文章"""
        # 假如发表一篇文章,并已经得到了文章对象article
        return redirect('article:article_detail', article_id=article.id)
    
    • 1
    • 2
    • 3
    • 4

    3.直接通过硬编码指定路径。

    这种方式不推荐,代码如下:

    def article_publish(request):
        """发表文章"""
        # 假如发表一篇文章,并已经得到了文章对象article
        to = 'article/' + article.id + '/detail/'
        return redirect(to)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.get_object_or_404

    在插叙你指定模型的数据时,Django中封装了ORM支持三种处理方式:1.通过模型类的objects属性进行查询;2.通过模型类提供的管理器对象Manager进行查询;3.通过定义模型类的静态方法进行查询。项目中常用第三种。

    get_object_or_404函数用于查询指定数据,如果数据不存在或存在多条,直接返回404错误。

    重构查询指定编号的文章的函数,如下:

    def article_detail(request, article_id):
        """查询指定编号的文章,article_id变量会接受路由中传递的数据"""
        print("查询指定编号的文章,编号:%s" % article_id)
        article = get_object_or_404(Article, pk=article_id)
        return redirect(article)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.get_list_or_404

    查询指定类型的多条数据,如果数据不存在,直接返回404错误。

    重构文章查询的相关函数,代码如下:

    from django.shortcuts import render, redirect, get_object_or_404, get_list_or_404
    
    from article.models import Article
    
    
    def article_list(request):
        """查询指文章列表"""
        articles = get_list_or_404(Article)
        return render(request, 'article/articles.html', {'articles': articles})
    
    
    def article_year(request, year):
        """查询指定年份的文章,year变量会接受路由中传递的数据"""
        articles = get_list_or_404(Article, pub_time__year=year)
        return render(request, 'article/articles.html', {'articles': articles})
    
    
    def article_month(request, year, month):
        """查询指定月份的文章,year和month变量会接受路由中传递的数据"""
        articles = get_list_or_404(Article, pub_time__year=year, pub_time__month=month)
        return render(request, 'article/articles.html', {'articles': articles})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    注意:如果要使用__month这样的日期时间条件,则必须在配置文件添加时间配置选项,一般配置LANGUAGE_CODE = ‘zh-Hans’,通是一定要添加USE_TZ = False,来关闭时间自动转换,才能正常存储时间和使用日期时间的限定条件查询数据对象。

    视图相关装饰器

    Django有一些和网站数据访问有关的功能,被封装成装饰器,主要有如下4中形式。

    1.基于请求访问的装饰器

    装饰器描述
    django.views.decorators.http.require_http_methodsHTTP规范的请求方式
    django.views.decorators.http.require_GET只允许GET请求方式
    django.views.decorators.http.require_POST只允许POST请求方式
    django.views.decorators.http.require_safe允许安全的GET/HEAD请求方式

    示例:

    @require_http_methods(['GET', 'POST'])
    def author_register(request):
    	....
    
    
    • 1
    • 2
    • 3
    • 4

    2.基于数据优化的装饰器

    项目汇总有些数据修改少,但是查询多,可以使用django.views.decorators.http.condition装饰器实现。具体细节后面讲解。

    3.基于响应优化的装饰器

    目前主流的浏览器都支持gzip压缩/解压缩操作,可以将数据通过gzip压后返回给客户端,节省流量。示例如下:

    @gzip_page
    def articles_author(request, author_id):
        '''查询指定作者的所有文章'''
        # 查询得到作者对象
        author = get_object_or_404(Author, pk=author_id)
        # 查询作者的所有文章
        articles = author.article_set.all()
        return render(request, 'article/articles.html', {'articles': articles})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4.基于缓存的网站性能优化

    比如django.views.decorators.cache,可以用于缓存。具体缓存在后面有专门的章节讲。

  • 相关阅读:
    面向对象的设计-设计模式-5种创建型模式
    【电路笔记】-电路中的复数与相量(Phasor)
    LVGL官方+100ASK合力打造的中文输入(拼音输入法)组件,让LVGL支持中文输入!
    ZEMAX | 探索 OpticStudio中的序列模式
    pwnable.kr--pwn游戏之fd
    西安---高时空分辨率、高精度一体化预测技术之风、光、水能源自动化预测技术应用
    webpack快速入门-核心概念
    webpack的简单使用
    spring boot自定义配置时在yml文件输入有提示
    逆向第一课---安装ADB工具,并使用夜神模拟器连接
  • 原文地址:https://blog.csdn.net/qq_43745578/article/details/127954188