Django来敲门~第一部分【6.2 HTML视图模板】

天下难事必作於易。天下大事必作於细。是以圣人终不为大,故能成其大 ——老子《道德经》


本节内容

  • HTML页面的渲染
  • 使用页面模板
  • 异常处理
  • 超链接路径处理
  • 路由命名空间

1. HTML页面渲染

在之前的章节中,我们使用的视图,都是临时在函数HttpResponse中添加的字符串,这样的数据明显不符合我们网页的需要,一个网页中那么多的文字、图片、视频音频等等数据,如果按照字符串的方式来处理的话明显不是很现实

网页开发有独立的技术进行处理,通常使用HTML/CSS/JavaScript/JQuery进行网页部分的开发,当然,大家如果这些技术稍有遗憾的话,可以上网多找资料学习一下的哦~~

接下来,上干货:渲染第一个HTML页面

1.1 渲染HTML网页
  • polls/应用目录下,创建一个名称为templates/文件夹,在文件夹中,创建一个名称为index.html的网页,添加如下内容
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>投票模块首页</title>
    <link rel="stylesheet" href="">
</head>
<body>  
    <h1>投票模块首页</h1>
</body>
</html>
  • 修改polls/views.py中的index函数,如下:
from django.template import loader
from django.http import HttpResponse
# 定义首页处理函数
def index(request):
    # 获取模板页面
    temp = loader.get_template("index.html")
    # 保存数据的上下文对象
    context = {}
    # 渲染视图
    return HttpResponse(temp.render(context, request))
  • OK,接下来,启动服务,访问以下http://localhost:8000/polls,看看结果哦

使用html网页进行视图开发

注意:通常情况下,我们会将要使用的html网页,保存在应用的templates/文件夹下,因为django在视图处理函数中,通过loader.get_template()函数进行加载的时候,会默认从templates/文件夹下进行搜索查询。此时,你明白为什么要创建一个templates/文件夹了ma?

1.2. 渲染网页的快捷方式

上述代码中,将一个HTML网页做成了视图模板,在我们的web项目中可以使用了,但是操作过程比较麻烦: 首先需要通过loader对象的get_template()函数加载网页 然后还有一个保存数据的上下文对象 最后需要通过HttpResonse函数进行渲染才能给浏览器查看到。

Django为了方便我们进行HTML网页视图模板的处理,提供了一个快捷进行网页模板渲染的方式:render() 上干货:修改上面的index函数中的视图处理的代码:

from django.shortcuts import render
# 修改首页处理函数
def index(request):
    # 返回渲染视图对象
    return render(request, "index.html", {})

Bingo!这个世界清净了。赶紧试试吧!!!

2. 使用页面模板

目前来说,HTML网页已经正常的显示在我们的浏览器中

此时有个非常重要的问题需要解决,什么问题呢?我们Django中定义的数据,怎么展示到HTML网页中呢?

如果,如果我说,这里的HTML网页中,可以写类似python代码!惊不惊喜意不意外! 此处应播放 类似爱情

在template/文件夹下的html网页,可以在一对特殊的符号中编写类似python的模板语法的代码,这个符号就是{%这里可以写类似python的模板语法的代码%} 同时,在html页面中,可以通过一对双大括号,来访问python对象的属性,如{{question.question_text}}

干货来袭,改造首页处理函数和首页index.html


改造首页处理函数,查询所有的对象,然后保存到上下文对象中

from django.template import loader
from .models import Question
# 处理首页的函数
def index(request):
    questionList = Question.objects.order_by("-pub_date")
    return render(request, "index.html", {"question_list" : questionList})

改造首页index.html,用于展示所有查询到的问题

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>投票模块首页</title>
    <link rel="stylesheet" href="">
</head>
<body>  
    <h1>投票模块首页</h1>
       {%if question_list%}
          <ul>
          {%for question in question_list%}
              <li><a href="/polls/{{qustion.id}}">{{question.question_text}}</a></li>
          {%endfor%}
          </ul>
       {%else%}
          <p>没有要处理的问题</p>
       {%endif%}
</body>
</html>

Bingo!接下来,重启一下项目,然后在浏览器中访问一下看看吧

使用页面模板语法展示数据

3. 异常处理

软件开发,总是一个问题接着一个问题,一个Bug跟着一堆Bug;尤其是需求变动频繁的情况下,看着需求经理和产品经理,心理已经默默的将满清十八大酷刑轮了好几遍! 不过,话说回来,不就是应该变动这么快的需求,要求这么严格的产品,软件开发才造就了高薪么。

那么问题来了!如果我们前面写的项目,用户访问了不存在的问题编号,会出现什么问题呢?来吧来吧~看看先!

3.1. 异常的出现——潜在Bug

首先改造detail函数和对应的视图页面detail.html 改造detail函数如下:

# 定义和页面的绑定关系
def detail(request, question_id):
    # 根据主键编号查询一个问题对象
    question = Question.objects.get(pk=question_id)
    return render(request, "details.html", {"question":question})

改造detail.html函数

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>详细问题展示</title>
    <link rel="stylesheet" href="">
</head>
<body>
    <h1>详细问题展示页面</h1>
    {%if question%}
        <p>问题编号:{{question.id}}</p>
        <p>问题描述:{{question.question_text}}</p>
    {%else%}
        <p>没有问题</p>
    {%endif%}
</body>
</html>

此时,入门在访问问题详细页面时,如果修该浏览器中的id编号,会出现如下的异常

项目异常情况

3.2. 处理异常

页面出现的异常情况,我们有一些特殊的状态处理方式,如常规情况下在HTTP协议中有一些特殊的状态编码,如404表示访问的资源不存在,500表示服务器内部错误等等,在Django中,我们也可以这么干

首先,捕获到用户访问的数据不存在的异常,然后抛出一个异常对象 改造polls/views.py中的detail函数如下:

from django.http import Http404
# 问题详情函数
def detail(requst, question_id):
    try:
         question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("您要找的问题不存在,问题编号:%s" % question_id)
    return render(request, "detail.html", {"question": question})

此时,如果我们重新访问一个不存在的编号:

添加异常处理后的错误页面

3.3. 针对web异常的快捷处理方式

通常情况下,类似查询数据访问对应的模板页面,无非就两种情况,有或者没有。有就返回数据,没有就返回404,针对两种结果,django封装了一个好玩的函数来进行处理

# 获取对象,如果对象不存在就抛出404异常
get_object_or_404()

我们改造一下detail视图处理函数

# 引入需要的模块
from django.shortcuts import render, get_object_or_404
# 改造函数
def detail(request, question_id):
    #查询对象,如果不存在就抛出异常
    question = get_object_or_404(Question, pk=question_id)
    return render(request, "detail.html", {"question":question})

页面访问的404错误页面

3.4. 补充:关于开发模式和生产模式

在我们目前的章节中,默认是使用开发模式【就是适合代码开发的软件环境,有更多的错误提示信息】,包括页面的展示也是使用的开发模式的错误提示

在进行项目发布时,需要将开发模式转换成生产模式【适合实际使用的软件环境,错误提示或者错误引起的软件的乱码等都会隐藏】

将开发模式转换成生成模式 修改mysite/settings.py配置文件

# 关闭调试【关闭开发模式】
DEBUG = False
# 一旦修改成生产模式,需要在ALLOWED_HOST中添加允许访问的主机列表
ALLOWED_HOSTS = ["localhost", "127.0.0.1"]

此时我们如果访问错误页面,就会出现下面这样的风格

生产环境下的错误页面,非常简洁哦

4. 超链接路径处理

在前面的案例项目中,在页面部分使用的是硬编码的形式进行了超链接路径指定

<li><a href="/polls/{{question_id}}">{{question.question_text}}</a></li>

这样的形式并不是特别适合实际项目开发,会出现各种路径维护的问题(如模块路径更换、路由路径更新会造成大量的项目改造非常麻烦),所以可以使用路由指定的形式来记性处理,如下:

# 使用url进行路由指定即可,避免了硬编码造成的问题
<li><a href="{%url 'detail' question_id%}"></a></li>

注意,这里的url编码配置,和urls.py文件中的配置必须对应

编码配置执行过程

5.路由命名空间

第4节我们对路由从硬编码改造成了配置实现的方式,方便了项目中的操作

但是,此时我们只有一个模块应用,当项目中出现多个模块的应用,同时多个模块应用下又有重名的路由时,这样的配置方式同样是有问题的:

|-- mysite/
    |-- polls/
        |-- templates/
            |--details.html
            |-- ......
        |-- ....
    |-- shop/
        |-- templates/
            |-- details.html
            |-- ......
        |-- ....

路由配置如下:

polls/urls.py
--------------------------
urlpatterns = [
     ....
     url(r"^(?P<detail_id>\d+)$", views.detail, name="detail"),
     ....
]
***************************************************************
shop/urls.py
--------------------------
urlpatterns = [
     ....
     url(r"^(?P<goods_id>\d+)$", views.detail, name="detail"),
     ....
]

此时,我们如果在页面中,通过前面的编码的方式,就会出现非常不明确的跳转方式

<li><a href="{%url 'detail' question_id%}"></a></li>
# ?问题?你是要跳转大polls/detial还是shop/detail呢?

Bingo!此时就是我们路由的命名空间登场了,在urls.py模块中,增加一个app_name来定义一个路由的命名空间,后续的路由操作,可以通过命名空间的形式来指定路径了。

修改路由配置如下:

polls/urls.py
--------------------------
app_name="polls"
urlpatterns = [
     ....
     url(r"^(?P<detail_id>\d+)$", views.detail, name="detail"),
     ....
]
***************************************************************
shop/urls.py
--------------------------
app_name="shop"
urlpatterns = [
     ....
     url(r"^(?P<goods_id>\d+)$", views.detail, name="detail"),
     ....
]

然后我们就可以这样用了

# 这是跳转到polls的detaild的链接【命名空间:路由名称】
<li><a href="{%url 'polls:detail' question_id%}"></a></li>

这节课就先到这里,下一节,我们进入表单处理部分


本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端小叙

微信公众号复制的图片可以正常显示的办法

通过浏览多方文章,找到了一个 非常好用但是也有很大的坑的办法: 在页面中加meta: <meta name="referrer" content="never"...

2.7K90
来自专栏西枫里博客

宝塔面板下升级到PHP7.2,无法查看phpinfo的解决办法。

自从建站后没多久,就把PHP的版本升级到7了,后续有升级到7.2了,一直也没关注过phpinfo的信息,今天小伙伴在群里说我草,phpinfo都看不到,我大概想...

22420
来自专栏网络

那些年,我们用过的fiddler

在测试中,不管是做手工测试,还是接口测试,我们都需要查看后端返回的数据。有的时候,我们也需要调试,或者mock一下后端的返回,来验证前端是否达到预期。 为了捕获...

199100
来自专栏大数据钻研

HTML meta标签总结与属性使用介绍

之前学习前端中,对meta标签的了解仅仅只是这一句。 <metacharset="UTF-8"> 但是打开任意的网站,其head标签内都有一列的meta标签。比...

34660
来自专栏马涛涛的专栏

webpack@3简单使用

这篇博客用的是webpack3的版本,作为入门理解学习 非原创,只为学习记录。博客大部分内容引用来源如下:

28060
来自专栏云计算教程系列

如何在Windows 10上安装Ruby并设置本地编程环境

Ruby是一种动态编程语言,可用于编写从简单脚本到游戏和Web应用程序的任何内容。它于1993年首次在日本发布,但在2005年作为服务器端Web开发的语言获得了...

46500
来自专栏FreeBuf

前端黑魔法之远程控制地址栏

由于今天看到一篇文章《危险的 target=”_blank” 与 “opener”》,里面提到了一个老知识点,就是target=”_blank”的时候,新打开的...

36640
来自专栏vue学习

webpack入门

前言:这两天在网上找了些视频和资料学习webpack,最后发现官网上的教程原来就写得很好,只是都是全英文的一开始不想去看。。。。今天认真看了下官网教程,然后总结...

22320
来自专栏Crossin的编程教室

Python 与 Excel 不得不说的事

数据处理是 Python 的一大应用场景,而 Excel 则是最流行的数据处理软件。因此用 Python 进行数据相关的工作时,难免要和 Excel 打交道。 ...

37860
来自专栏FreeBuf

挖洞经验 | 记一次曲折的Getshell过程

最近在挖某框架的漏洞,其中挖到一枚Getshell,挖的过程有点曲折感觉可以写篇文章总结一下,方便与各位大牛交流交流。 因为此框架有大量用户,并且此漏洞并未修复...

35790

扫码关注云+社区

领取腾讯云代金券