天下难事必作於易。天下大事必作於细。是以圣人终不为大,故能成其大

——老子《道德经》


本节内容

  • 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网页,保存在应用的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})

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>

最新文章

  1. (哈夫曼树)HuffmanTree的java实现
  2. 简单理解Socket
  3. iOS上线...踩坑
  4. 不起眼却有大作用的 .NET功能集(转发)
  5. 如何学习一个新的PHP框架
  6. sublime text 2使用经验
  7. spring heibernate 调用存储过程
  8. VS2012 快捷键 VS Resharper 设置
  9. Apache和PHP的优化
  10. GET请求和POST请求的区别
  11. [NOIP2011] 聪明的质监员 二分+前缀和
  12. 官方JwPlayer去水印步骤
  13. matplotlib学习笔记
  14. js dictionary
  15. 团队第十次 # scrum meeting
  16. jq 获取下一个兄弟原素 下拉箭头旋转
  17. The server principal &quot;sa&quot; is not able to access the database &quot;xxxx&quot; under the current security context
  18. QQ使用的使用评价
  19. Orchard Core 模块化
  20. PHP获取访客ip、系统、浏览器等信息[转]

热门文章

  1. Error:全局变量不明白(using namespace std 与全局变量的冲突)
  2. 2015南阳CCPC A - Secrete Master Plan A.
  3. jQuery 自定义动画效果
  4. 手把手教你把Vim改装成一个IDE编程环境(图文)【转】
  5. nodejs Yarn替代npm的包管理——快速、安全、可靠性高的依赖管理
  6. [App Store Connect帮助]三、管理 App 和版本(1)添加 App 至您的帐户
  7. 关于swoole 和golang 的压力测试结果
  8. 命令框中oracle dmp文件的导入和导出(仅做个人备忘)
  9. Java Web框架前景浅析
  10. JS——轮播图简单版