Python+Django+SAE系列教程10-----Django的模板

Python+Django+SAE系列教程10-----Django的模板

原创 2014年04月21日 17:32:24

这一章我们开始介绍模板,在前一章中,你可能已经注意到我们在例子视图中返回文本的方式有点特别。 也就是说,HTML被直接硬编码在 Python 代码之中。这样的确有点BT。

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

如果我们学习了模板,就不会在这样BT了,再Django中模板其实就是一个html文件,我先来看一个简单的例子:

<html>
<head><title>订单</title></head>

<body>

<h1>订单</h1>

<p>尊敬的 {{ person_name }},</p>

<p>感谢来您订购的来自 {{ company }} 的订单. 订单时间为: {{ ship_date|date:"F j, Y" }}.</p>

<p>这里是您的订货列表:</p>

<ul>
{% for item in item_list %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

{% if ordered_warranty %}
    <p>您的保修信息将包含在包裹中。</p>
{% else %}
    <p>你没有定购保修要求, 所以,如果机器停止运行您将自己负责。</p>
{% endif %}

<p>张三,<br />{{ company }}</p>

</body>
</html>
用两个大括号括起来的文字(例如 {{ person_name }} )称为 变量(variable) 。这意味着在此处插入指定变量的值。


被大括号和百分号包围的文本(例如 {% if ordered_warranty %} )是 模板标签(template tag) 。标签(tag)定义比较明确,即: 仅通知模板系统完成某些工作的标签。其实就是写代码和语句的地方。


这个模板的第二段中有一个关于filter过滤器的例子,它是一种最便捷的转换变量输出格式的方式。 如这个例子中的{{ship_date|date:”F j, Y” }},我们将变量ship_date传递给date过滤器,同时指定参数”F j,Y”。date过滤器根据参数进行格式输出。 过滤器是用管道符(|)来调用的,具体可以参见Unix管道符。其实这里我更喜欢在后台过滤这些信息,因为我们不能要求美工或者参与布局设计的人员有太多编程的基础,所以教程里面关于模版的介绍暂时可以忽略了。


了解了模板,我们现在就来创建一个模板,以及看看在视图中是如何应用的。下面我们先创建一个名为template的文件夹,这个文件夹里面将会放入我们编辑的模板,就是html文件。然后我们需要在setting.py这个文件中找到“TEMPLATE_DIRS =”,然后告诉 Django 的模板加载机制在哪里查找模板。 选择一个目录用于存放模板并将其添加到TEMPLATE_DIRS 中:

TEMPLATE_DIRS = ("Bidding/templates"

)
其实这里的目录以及路径可以自己制定,只需要在setting里面设置一下就ok了,这里也可以使用绝对路径如 :

TEMPLATE_DIRS = (
    'C:/www/django/templates',
)
完成 TEMPLATE_DIRS 设置后,下一步就是修改视图代码,让它使用 Django 模板加载功能而不是对模板路径硬编码。 返回 current_datetime 视图,进行如下修改:

from django.shortcuts import render_to_response
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    return render_to_response('current_datetime.html', {'current_date': now})

我们不再需要导入 get_template 、 Template 、 Context 和 HttpResponse 。相反,我们导入 django.shortcuts.render_to_response 。 import datetime 继续保留。

在 current_datetime 函数中,我们仍然进行 now 计算,但模板加载、上下文创建、模板解析和 HttpResponse 创建工作均在对 render_to_response() 的调用中完成了。 由于 render_to_response() 返回 HttpResponse 对象,因此我们仅需在视图中 return 该值。


render_to_response() 的第一个参数必须是要使用的模板名称。 如果要给定第二个参数,那么该参数必须是为该模板创建 Context 时所使用的字典。 如果不提供第二个参数, render_to_response() 使用一个空字典。


这里面的 {'current_date': now} 需要说明一下:now为在视图里面的变量,而current_date 则是模板中的变量。其实如果这两个变量一直的话,我们可以简化写成这样:

from django.shortcuts import render_to_response
import datetime

def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response('current_datetime.html', locals())
把所有的模板都存放在一个目录下可能会让事情变得难以掌控。 你可能会考虑把模板存放在你模板目录的子目录中,这非常好。也可以这样:

return render_to_response('dateapp/current_datetime.html', locals())
Windows用户必须使用斜杠而不是反斜杠。说了这么多,我想你一定和我一样想试试这个模板了。上面已经介绍了views.py的修改内容,下面我们来创建一个模板current_datetime.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>显示当前时间</title>
</head>
<body>
    <h1>这仅仅是一个简单的例子</h1>
    <hr>
    <p>当前时间为:{{ current_date }}</p>
</body>
</html>

然后我们把current_datetime.html文件放入templates。
在这之前确保一下几个步骤已经完成
1.修改了setting中的TEMPLATE_DIRS = ("Bidding/templates")
2.修改了views.py
from django.shortcuts import render_to_response
import datetime

def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response('current_datetime.html', locals())
然后上传代码,看效果把。


下面我们来看看include 模板标签,就是模板里面可以套模板,首先我们在template目录里面再创建一个base的目录,在这里目录里面我们准备放上网页的top和bottom的模板。
top.html:

<div style="background:#eeeeee;width:100%;height:60px;">
    学习python是个快乐的过程----{{ author }}
</div>

bottom.html:

<div style="background:#eeeeee;width:100%;height:30px;">
    版权所有----{{ author }}
</div>
然后我们再建立一个新的模板,把他放在template根目录里面,命名为template_include.html

template_include.html:

<html>
<body>
{% include "base/top.html" %}
<h1>再过 {{ offset }} 个小时, 时间将会是 {{ dt }}.</h1>
{% include "base/bottom.html" %}
</body>
</html>
然后我们在修改一下之前的 hours_ahead 视图:
def hours_ahead(request, offset):
    try:
        offset = int(offset)
    except ValueError:
        raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    author="hemeng80"
    return render_to_response('template_include.html', locals())
到目前为止,我们的模板范例都只是些零星的 HTML 片段,但在实际应用中,你将用 Django 模板系统来创建整个 HTML 页面。 这就带来一个常见的 Web 开发问题: 在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码?


解决该问题的传统做法是使用 服务器端的 includes ,你可以在 HTML 页面中使用该指令将一个网页嵌入到另一个中。 事实上, Django 通过刚才讲述的 {% include %} 支持了这种方法。 但是用 Django 解决此类问题的首选方法是使用更加优雅的策略—— 模板继承 。


首先我们建立一个基类模板命名为 base.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <h1>这里是一个学习用的测试网站</h1>
    {% block content %}{% endblock %}
    {% block footer %}
    <hr>
    <p>感谢你的访问</p>
    {% endblock %}
</body>
</html>
现在我们已经有了一个基本模板,我们可以在建立一个 hello_base.html 模板来 使用它:

{% extends "base.html" %}

{% block title %}欢迎{% endblock %}

{% block content %}
<p>这时我的第一个Python程序: {{ MyString }}.</p>
{% endblock %}
在改造一下views.py:

# -*- coding: utf-8 -*-
from django.http import HttpResponse
from django.shortcuts import render_to_response
import datetime

def hello(request):
    return HttpResponse('Hello world') 

def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response('current_datetime.html', locals())

def hours_ahead(request, offset):
    try:
        offset = int(offset)
    except ValueError:
        raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    author="hemeng80"
    return render_to_response('template_include.html', locals())


def hello_base(request):
    MyString = 'Hello world'
    return render_to_response('hello_base.html', locals())
在配置下urls.py:

from django.conf.urls import patterns, include, url


# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'Bidding.views.home', name='home'),
    # url(r'^Bidding/', include('Bidding.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    # url(r'^admin/', include(admin.site.urls)),
    url(r'^hello/$', 'Bidding.views.hello'),
    url(r'^time/$', 'Bidding.views.current_datetime'),
    url(r'^time/plus/(\d{1,2})/$', 'Bidding.views.hours_ahead'),
    url(r'^hello_base/$', 'Bidding.views.hello_base'),
)
在看看程序的运行结果,你一定可以了解模板的包含、继承的意义了!








  • 本文已收录于以下专栏:

Python+Django+SAE系列教程11-----request/pose/get/表单

Python+Django+SAE系列教程11-----request/pose/get/表单
  • hemeng
  • hemeng
  • 2014年05月07日 19:09
  • 2709

Python+Django+SAE系列教程14-----使表单更安全

Python+Django+SAE系列教程14-----使表单更安全
  • hemeng
  • hemeng
  • 2014年05月08日 19:40
  • 1710
'); (window.slotbydup=window.slotbydup || []).push({ id: '4765209', container: s, size: '808,120', display: 'inlay-fix' }); })();

Python+Django+SAE系列教程12-----配置MySQL数据库

Python+Django+SAE系列教程12-----配置MySQL数据库
  • hemeng
  • hemeng
  • 2014年05月07日 19:48
  • 4799

Python+Django+SAE系列教程15-----输出非HTML内容(图片/PDF)

Python+Django+SAE系列教程15-----输出非HTML内容(图片/PDF)
  • hemeng
  • hemeng
  • 2014年06月06日 11:57
  • 3321

Python+Django+SAE系列教程3-----Python中的面向对象编程

Python+Django+SAE系列教程3-----Python中的面向对象编程
  • hemeng
  • hemeng
  • 2014年04月15日 09:57
  • 1787
'); (window.slotbydup=window.slotbydup || []).push({ id: '4983339', container: s, size: '808,120', display: 'inlay-fix' }); })();

Python+Django+SAE系列教程2-----Python种的函数、模块和数据结构

Python+Django+SAE系列教程2-----Python种的函数、模块和数据结构
  • hemeng
  • hemeng
  • 2014年03月10日 23:50
  • 1932

Python+Django+SAE系列教程1-----Python环境和基本语法

由于本系列内容是基于SAE的,目前SAE支持的Python版本是2.7.3,所以我们先安装这个版本的Python,下载地址:http://www.skycn.com/soft/appid/10554....

Python+Django+SAE系列教程1-----Python环境和基本语法

Python+Django+SAE系列教程1-----Python环境和基本语法
  • hemeng
  • hemeng
  • 2014年03月10日 23:40
  • 2629

Python+Django+SAE系列教程6-----本地配置Django

Python+Django+SAE系列教程6-----本地配置Django
  • hemeng
  • hemeng
  • 2014年04月21日 16:53
  • 2758

Python+Django+SAE系列教程9-----Django的视图和URL

Python+Django+SAE系列教程9-----Django的视图和URL
  • hemeng
  • hemeng
  • 2014年04月21日 17:23
  • 2404
'); (window.slotbydup=window.slotbydup || []).push({ id: '5384130', container: s, size: '300,300', display: 'inlay-fix' }); })();
'); (window.slotbydup=window.slotbydup || []).push({ id: '4770930', container: s, size: '300,250', display: 'inlay-fix' }); })();
不良信息举报
您举报文章:Python+Django+SAE系列教程10-----Django的模板
举报原因:
原因补充:

(最多只允许输入30个字)

btn_cancel.jpg

这一章我们开始介绍模板,在前一章中,你可能已经注意到我们在例子视图中返回文本的方式有点特别。 也就是说,HTML被直接硬编码在 Python 代码之中。这样的确有点BT。

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

如果我们学习了模板,就不会在这样BT了,再Django中模板其实就是一个html文件,我先来看一个简单的例子:

<html>
<head><title>订单</title></head>

<body>

<h1>订单</h1>

<p>尊敬的 {{ person_name }},</p>

<p>感谢来您订购的来自 {{ company }} 的订单. 订单时间为: {{ ship_date|date:"F j, Y" }}.</p>

<p>这里是您的订货列表:</p>

<ul>
{% for item in item_list %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

{% if ordered_warranty %}
    <p>您的保修信息将包含在包裹中。</p>
{% else %}
    <p>你没有定购保修要求, 所以,如果机器停止运行您将自己负责。</p>
{% endif %}

<p>张三,<br />{{ company }}</p>

</body>
</html>
用两个大括号括起来的文字(例如 {{ person_name }} )称为 变量(variable) 。这意味着在此处插入指定变量的值。


被大括号和百分号包围的文本(例如 {% if ordered_warranty %} )是 模板标签(template tag) 。标签(tag)定义比较明确,即: 仅通知模板系统完成某些工作的标签。其实就是写代码和语句的地方。


这个模板的第二段中有一个关于filter过滤器的例子,它是一种最便捷的转换变量输出格式的方式。 如这个例子中的{{ship_date|date:”F j, Y” }},我们将变量ship_date传递给date过滤器,同时指定参数”F j,Y”。date过滤器根据参数进行格式输出。 过滤器是用管道符(|)来调用的,具体可以参见Unix管道符。其实这里我更喜欢在后台过滤这些信息,因为我们不能要求美工或者参与布局设计的人员有太多编程的基础,所以教程里面关于模版的介绍暂时可以忽略了。


了解了模板,我们现在就来创建一个模板,以及看看在视图中是如何应用的。下面我们先创建一个名为template的文件夹,这个文件夹里面将会放入我们编辑的模板,就是html文件。然后我们需要在setting.py这个文件中找到“TEMPLATE_DIRS =”,然后告诉 Django 的模板加载机制在哪里查找模板。 选择一个目录用于存放模板并将其添加到TEMPLATE_DIRS 中:

TEMPLATE_DIRS = ("Bidding/templates"

)
其实这里的目录以及路径可以自己制定,只需要在setting里面设置一下就ok了,这里也可以使用绝对路径如 :

TEMPLATE_DIRS = (
    'C:/www/django/templates',
)
完成 TEMPLATE_DIRS 设置后,下一步就是修改视图代码,让它使用 Django 模板加载功能而不是对模板路径硬编码。 返回 current_datetime 视图,进行如下修改:

from django.shortcuts import render_to_response
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    return render_to_response('current_datetime.html', {'current_date': now})

我们不再需要导入 get_template 、 Template 、 Context 和 HttpResponse 。相反,我们导入 django.shortcuts.render_to_response 。 import datetime 继续保留。

在 current_datetime 函数中,我们仍然进行 now 计算,但模板加载、上下文创建、模板解析和 HttpResponse 创建工作均在对 render_to_response() 的调用中完成了。 由于 render_to_response() 返回 HttpResponse 对象,因此我们仅需在视图中 return 该值。


render_to_response() 的第一个参数必须是要使用的模板名称。 如果要给定第二个参数,那么该参数必须是为该模板创建 Context 时所使用的字典。 如果不提供第二个参数, render_to_response() 使用一个空字典。


这里面的 {'current_date': now} 需要说明一下:now为在视图里面的变量,而current_date 则是模板中的变量。其实如果这两个变量一直的话,我们可以简化写成这样:

from django.shortcuts import render_to_response
import datetime

def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response('current_datetime.html', locals())
把所有的模板都存放在一个目录下可能会让事情变得难以掌控。 你可能会考虑把模板存放在你模板目录的子目录中,这非常好。也可以这样:

return render_to_response('dateapp/current_datetime.html', locals())
Windows用户必须使用斜杠而不是反斜杠。说了这么多,我想你一定和我一样想试试这个模板了。上面已经介绍了views.py的修改内容,下面我们来创建一个模板current_datetime.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>显示当前时间</title>
</head>
<body>
    <h1>这仅仅是一个简单的例子</h1>
    <hr>
    <p>当前时间为:{{ current_date }}</p>
</body>
</html>

然后我们把current_datetime.html文件放入templates。
在这之前确保一下几个步骤已经完成
1.修改了setting中的TEMPLATE_DIRS = ("Bidding/templates")
2.修改了views.py
from django.shortcuts import render_to_response
import datetime

def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response('current_datetime.html', locals())
然后上传代码,看效果把。


下面我们来看看include 模板标签,就是模板里面可以套模板,首先我们在template目录里面再创建一个base的目录,在这里目录里面我们准备放上网页的top和bottom的模板。
top.html:

<div style="background:#eeeeee;width:100%;height:60px;">
    学习python是个快乐的过程----{{ author }}
</div>

bottom.html:

<div style="background:#eeeeee;width:100%;height:30px;">
    版权所有----{{ author }}
</div>
然后我们再建立一个新的模板,把他放在template根目录里面,命名为template_include.html

template_include.html:

<html>
<body>
{% include "base/top.html" %}
<h1>再过 {{ offset }} 个小时, 时间将会是 {{ dt }}.</h1>
{% include "base/bottom.html" %}
</body>
</html>
然后我们在修改一下之前的 hours_ahead 视图:
def hours_ahead(request, offset):
    try:
        offset = int(offset)
    except ValueError:
        raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    author="hemeng80"
    return render_to_response('template_include.html', locals())
到目前为止,我们的模板范例都只是些零星的 HTML 片段,但在实际应用中,你将用 Django 模板系统来创建整个 HTML 页面。 这就带来一个常见的 Web 开发问题: 在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码?


解决该问题的传统做法是使用 服务器端的 includes ,你可以在 HTML 页面中使用该指令将一个网页嵌入到另一个中。 事实上, Django 通过刚才讲述的 {% include %} 支持了这种方法。 但是用 Django 解决此类问题的首选方法是使用更加优雅的策略—— 模板继承 。


首先我们建立一个基类模板命名为 base.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <h1>这里是一个学习用的测试网站</h1>
    {% block content %}{% endblock %}
    {% block footer %}
    <hr>
    <p>感谢你的访问</p>
    {% endblock %}
</body>
</html>
现在我们已经有了一个基本模板,我们可以在建立一个 hello_base.html 模板来 使用它:

{% extends "base.html" %}

{% block title %}欢迎{% endblock %}

{% block content %}
<p>这时我的第一个Python程序: {{ MyString }}.</p>
{% endblock %}
在改造一下views.py:

# -*- coding: utf-8 -*-
from django.http import HttpResponse
from django.shortcuts import render_to_response
import datetime

def hello(request):
    return HttpResponse('Hello world') 

def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response('current_datetime.html', locals())

def hours_ahead(request, offset):
    try:
        offset = int(offset)
    except ValueError:
        raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    author="hemeng80"
    return render_to_response('template_include.html', locals())


def hello_base(request):
    MyString = 'Hello world'
    return render_to_response('hello_base.html', locals())
在配置下urls.py:

from django.conf.urls import patterns, include, url


# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'Bidding.views.home', name='home'),
    # url(r'^Bidding/', include('Bidding.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    # url(r'^admin/', include(admin.site.urls)),
    url(r'^hello/$', 'Bidding.views.hello'),
    url(r'^time/$', 'Bidding.views.current_datetime'),
    url(r'^time/plus/(\d{1,2})/$', 'Bidding.views.hours_ahead'),
    url(r'^hello_base/$', 'Bidding.views.hello_base'),
)
在看看程序的运行结果,你一定可以了解模板的包含、继承的意义了!








猜你喜欢

转载自blog.csdn.net/qq_30058597/article/details/78763875