/ 知识库     / 试卷库

Django模板

视频简介

django视图可以返回一个静态的字符串,也可以生成一个动态的网页。

为了让Django视图显示当前日期和时间,我们仅需要把语句:datetime.now()放入视图函数,然后返回一个HttpResponse对象即可。

   def current_datetime(request):
    now = datetime.datetime.now()
    html = "It is now %s." % now
    return HttpResponse(html)

不难发现,视图中返回文本的方式有点特别,即,HTML被直接硬编码在 Python 代码之中,这可不是一个好主意。

首先,对页面设计进行的任何改变都必须修改 Python 代码。 

其次,编写Python 代码和 设计HTML页面是两项不同的工作,大多数网站开发中都将他们分配给不同的人员(甚至不同部门)来完成。 

最后,程序员编写 Python代码和设计人员制作模板两项工作一般是同时进行的,其效率远胜于让一个人等待另一个人完成后再开始的串行工作机制。

基于上述原因,将页面设计和Python代码分离是高效而明智的做法。 Django模板系统正为此而生,这就是本章要讨论的问题。

【1】将上面的视图代码改为模型实现如下:

    from django.template import Template, Context
    from django.http import HttpResponse
    import datetime
    def current_datetime(request):
        now = datetime.datetime.now()
        t = Template("It is now {{ current_date }}.")
        html = t.render(Context({'current_date': now}))
        return HttpResponse(html)

这段代码确实使用了Django模板系统,但是并没有解决我们的问题。 也就是说,模板仍然嵌入在Python代码里,并未真正实现数据与表现的分离。 事实上,我们需要将模板置于一个单独的文件中,并且让视图加载该文件来解决该问题。

【2】假设文件保存在 项目/templates/mytemplate.html 中,代码就会像下面这样:

    from django.template import Template, Context
    import datetime
    def current_datetime(request):
        now = datetime.datetime.now()
        fp = open('c:/python/my_project/templates/mytemplate.html')
        t = Template(fp.read())
        fp.close()
        html = t.render(Context({'current_date': now}))
        return HttpResponse(html)

然而,这种实现方法依然存在较大风险:

首先,它没有对文件丢失的情况做出处理。 如果模板文件丢失或者不可读, open() 函数调用将会引发 IO异常。

其次,程序对文件的位置进行了硬编码。 如果每个视图函数都用该技术,就要不断复制这些模板的位置。

再次,程序包含了大量、重复文件操作代码。 在每次加载模板时都调用,如 open 、 read() 和 close()等。

作为改进方案,django提供了基于配置的模板自加载技术.

依然假设文件保存在 项目/templates/mytemplate.html 中,打开项目settings.py配置文件,找到TEMPLATE模块。

在DIR中告诉Django模板加载机制从哪里加载模板,'DIRS': ['c:/python/my_project/templates',],

【3】最省事的方式是使用绝对路径(即从文件系统根目录开始的目录路径)。 如果想要更灵活一点并减少一些负面干扰,可利用 Python 代码动态构建DIRS 的内容,如:

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

'DIRS': [os.path.join(BASE_DIR,'templates'),],

    from django.shortcuts import render
    from django.template.loader import get_template
    from django.template import Template, Context
    from django.http import HttpResponse
    import datetime
    def current_datetime(request):
        now = datetime.datetime.now()
        t = get_template('mytemplate.html')
        html = t.render({'current_date': now})
        return HttpResponse(html)

此例中,我们使用了函数 django.template.loader.get_template() ,而不是手动从文件系统加载模板。 该get_template() 函数以模板名称为参数,在文件系统中找出模块的位置,打开文件并返回一个编译好的Template 对象。

要注意的是:1.1版本中可以直接传入Context对象,在1.11后只能传入字典。

【4】render()

上面的例子讲述了模板文件的加载、渲染以及将处理好的HttpResponse对象给用户过程,主要通过get_template() 方法代替繁杂的代码来处理模板及其路径的工作。 但这仍然是一个普遍存在的重复性苦力劳动。为此,Django将此过程进行封装,提供了一个更简单的捷径,让我们一次性地载入某个模板文件,渲染它,然后将此作为 HttpResponse返回。

    django.shortcuts.render
    def current_datetime(request):
        now = datetime.datetime.now()
        return render(request,'mytemplate.html', {'current_date': now})

我们不再需要导入 get_template 、 Template 、 Context 和 HttpResponse 。相反,我们导入django.shortcuts.render。