Django(7):视图处理函数

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

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

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

1.视图处理函数的定义

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

from django.http import HttpResponse


def index(request):
    content = '<html><body><h1>hello views!</h1></body></html>'
    return HttpResponse(content)

每个视图处理函数默认都接受一个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'),
]

3.常见错误处理

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

def index(request):
	# 数据处理过程
    # 自定义错误
    if flag == 'OK':
        content = '<html><body><h1>hello views!</h1></body></html>'
        return HttpResponse(content)
    elif flag == 'NOT FOUND':
        return HttpResponseNotFound('<h1>404错误,要访问的页面不存在</h1>')
    elif flag == 'NOT DENIED':
        return HttpResponseNotAllowed('<h1>405错误,访问失败</h1>')
    elif flag == 'FORBIDDEN':
        return HttpResponseForbidden('<h1>403错误,没有权限访问该页面</h1>')
    elif flag == 'SERVERERROR':
        return HttpResponseServerError('<h1>500错误,服务器内部出现错误</h1>')

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

def index(request):
 	# 404错误页面
    try:
        # 数据处理过程
        content = '<html><body><h1>hello views!</h1></body></html>'
    except:
        raise Http404('page not found!')
    return HttpResponse(content)

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
)

参数:

  • 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>

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

from django.shortcuts import render


def index(request):
    return render(request, 'index.html', {'message': "欢迎访问博客"})

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)

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

2.redirect

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

参数:

  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})

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

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

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

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

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

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

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

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

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)

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})

注意:如果要使用__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):
	....

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})

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

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ethan-running

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

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

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

打赏作者

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

抵扣说明:

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

余额充值