Django教程--模板

模板

上节我们直接将html内容写在代码中直接输出,这样不利于html代码的复用和维护,所以需要模板系统来实现html代码和数据的分离,接下来我们就来学习Django中的模板系统。

  • 模板版Hello Django!
  • Django 模板教程
  • 加载静态资源

模板版Hello Django!

接着上节的HelloDjango项目,我们在HelloDjango目录下新建templates文件夹,然后在templates下新建index.html文件,文件内容如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>Hello Django!</title>
</head>
<body>
{{context}}
</body>
</html>

同时修改view.py的hello函数,修改后文件如下:

from django.shortcuts import render


def hello(request):
    return render(request,'index.html',{'context':'Hello Django!'})

然后我们需要在settings.py文件里设置模板文件夹路径,让Django可以找到,添加以下代码:
1.8版本前

TEMPLATE_DIRS={
    os.path.join(BASE_DIR,'HelloDjango/templates')
}

1.8版本及以后

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
           # templates 文件夹路径
        'DIRS': [os.path.join(BASE_DIR,'HelloDjango/templates'),],  
          
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

接下来需要同步数据库(上节没做),不执行可能会报错,执行以下命令

1.7版本前
python manage.py syncdb
1.7版本及往后
python manage.py migrate

然后启动服务,执行命令

python manage.py runserver 0.0.0.0:8000

再次访问即可看到同样的内容。


Django 模板教程

上面介绍了模板的简单使用,先来简单的解读下上诉代码,html中{{context}}是一个变量,render(request,'index.html',{'context':'Hello Django!'})的时候后面字典参数指定context的值,前面参数指定了模板的文件名。
接下来我们介绍模板的基本语法

  • 用{{}}包围的是变量,如{{context}},上面的例子中,我们给模板context传递了简单的值,大部分是string,以及一个datetime.date。尽管如此,模板可以传递更复杂的数据结构,如列表,字典和自定义对象模板中使用符号‘.’来访问复杂变量的成员(包括方法(无参数),字典的key,当方法发送异常时,字符串将会被渲染为空字符串),如上述代码修改为:
return render(request,'index.html',{'context':{'text':'Hello Django!'}})

在html中可以通过{{context.text}}来获取text的值,并且.符号可以嵌套使用。对于不合法的方法和变量,模板都会将其渲染为空字符串。

  • 用{%%}包围的是块标签,如{%if True%},块标签的含义很丰富,Django模板支持多种内建的块标签,并且你可以写你自己的标签来扩展模板的功能,下面介绍常用的几个标签:
    if/else
    {% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值系统则会显示{% if %}到{%else%}(如果存在)或{% endif %}(不存在)间的所有内容:
{% if today_is_weekend %}  
    <p>Welcome to the weekend!</p>  
{% else %}  
    <p>Get back to work.</p>  
{% endif %}  

{% if %}标签接受and,or或者not来测试多个变量值或者否定一个给定的变量,但是不允许在一个标签块同时使用and 和 or(可以多次都使用and或or),如果要实现该功能,需使用嵌套{%if%}来完成,同样不存在{%elif%}标签,实现此功能同样需要嵌套。
for
{% for %}标签允许你按顺序遍历一个序列中的各个元素
Python的for语句语法为for X in Y,X是用来遍历Y的变量
每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容,如

<ul>  
{% for athlete in athlete_list %}  
    <li>{{ athlete.name }}</li>  
{% endfor %}  
</ul>  

如需反向遍历,可以在标签添加reversed,用法如下:

{% for athlete in athlete_list  reversed%}  
    <li>{{ athlete.name }}</li>  
{% endfor %}

标签不支持break和continue,如果需要实现功能,请传递只包含想要遍历的变量的字典。
{% for %}标签内置了一个forloop模板变量,这个变量含有一些属性可以提供给你一些关于循环的信息
1.forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1,例如:

{% for item in todo_list %}  
    <p>{{ forloop.counter }}: {{ item }}</p>  
{% endfor %} 

2.forloop.counter0类似于forloop.counter,但它是从0开始计数,第一次循环设为0
3.forloop.revcounter表示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1
4.forloop.revcounter0类似于forloop.revcounter,但它是表示的数量少一个,即最后一次循环时设为0
5.forloop.first当第一次循环时值为True
6.forloop.last当最后一次循环时值为True
7.forloop.parentloop在嵌套循环中表示父循环的forloop:

{% for country in countries %}  
    <table>  
    {% for city in country.city_list %}  
        <tr>  
            <td>Country #{{ forloop.parentloop.counter }} </td>  
            <td>City #{{ forloop.counter }}</td>  
            <td>{{ city }}</td>  
        </tr>  
    {% endfor %}  
    </table>  
{% endfor %}  

ifequal/ifnotequal
{% ifequal %}比较两个值,类似于{%if%}标签,同样支持{%else%},{%ifnotequal%}与{%ifequal%}相反
include模板标签
这个标签允许你引入另一个模板的内容,标签的参数是你想引入的模板的名字,名字可以是变量,也可以是单引号或双引号表示的string
下面两个例子引入了模板nav.html的内容,这表示单引号和双引号都是允许的:

{% include 'nav.html' %}  
{% include "nav.html" %}  
{% include template_name %}  #template_name为变量,由渲染时动态指定

如果被引入的模板中包含任何的模板代码,如标签和变量等,它将用父模板的context计算它们
如果给定的模板名不存在,Django将做下面两件事情中的一件:
1.如果DEBUG设置为True,你将看到一个TemplateDoesNotExist异常的错误页面
2.如果DEBUG设置为False,标签将什么也不显示
模板继承
在web开发过程中,我们经常会遇到header或者footer相同的页面,django中可以使用模板继承来减少这些相同页面的冗余编码,这里先介绍下,具体如何使用会在后面的blog项目中介绍。
哲学和限制
Django的模板可能不同于jsp等其他模板引擎,他不允许你直接在模板中使用python代码,有时候为了实现某些功能可能需要很多代码(如if elif),但是这是django设计者所尊崇的设计哲学,业务逻辑应该和呈现逻辑分离,显示只做显示的事,业务的逻辑应交由后台来完成。当然你觉得Django的模板系统不好用的话,你也可以使用其他模板系统(1.8版本以后),具体做法为(更换为jinja2引擎):
在项目下建立jinja2_env.py

#from __future__ import absolute_import  # 如果是py2就取消这行的注释

from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse

from jinja2 import Environment


def environment(**options):
    env = Environment(**options)
    env.globals.update({
        'static': staticfiles_storage.url,
        'url': reverse,
    })
    return env

在settings.py里配置

#1.8版本及以后
TEMPLATES = [
    {
    #修改为其他模板引擎
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
           # templates 文件夹路径
        'DIRS': [os.path.join(BASE_DIR,'HelloDjango/templates'),],  
          
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
             'environment': 'APP_NAME.jinja2_env.environment',#配置环境
        },
    },
]

加载静态资源

html中通常需要加载图片和css/js等静态资源,需要做以下配置
在settings.py中添加以下代码:

STATIC_ROOT = os.path.join(BASE_DIR,'blog/static')#static目录
STATIC_URL = '/static/'#访问的url
STATICFILES_DIRS = (
    ("css", os.path.join(STATIC_ROOT,'css')),
    ("js", os.path.join(STATIC_ROOT,'js')),
    ("images", os.path.join(STATIC_ROOT,'images')),
)#static文件夹

在html中这样使用

<link href="{{STATIC_URL}}css/base.css" rel="stylesheet">

这样即可加载css文件,图片和js文件类似,其中{{STATIC_URL}}为settings.py中设置的STATIC_URL值,django模板会自动传入这个值。
参考链接:

  1. http://blog.csdn.net/zhangxinrun/article/details/8095118/
  2. http://blog.csdn.net/baidu_35085676/article/details/77206901

最近参加支付宝小程序比赛需要访问量,麻烦各位看官有空复制下面的话打开支付宝,搜索栏粘贴,在此多谢各位支持了

#JvCmawp74I1#长按复制此消息,打开支付宝搜索,体验南京疫情地图小程序
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,914评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,935评论 2 383
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,531评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,309评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,381评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,730评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,882评论 3 404
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,643评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,095评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,448评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,566评论 1 339
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,253评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,829评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,715评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,945评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,248评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,440评论 2 348

推荐阅读更多精彩内容