Haste makes waste

自强学堂-Django基础教程(2)-模板

Posted on By lijun

无意中在网上发现了这个网站自强学堂(作者还是校友),上面整理的教程都很不错,正好适合刚学完DjangoBasic篇之后的扩展。本系列作为该自强学堂教程的笔记,为节省时间,与DjangoBasic部分重叠的话,会省略。

注意:

Django的标签导致Jekyll无法编译,都修改为了[%[{,使用时需要替换将[替换为{


1. Django 模板

  • 按之前的步骤,新建app,并在settings.INSTALLED_APPS中加入 'learn',
  • 打开learn/views.py 写一个首页的视图
def index(request):
    return render(request, 'home.html')
  • learn目录下新建一个 templates 文件夹,里面新建一个 home.html,加入如下代码。
<!DOCTYPE html>
<html>
<head>
    <title>欢迎光临</title>
</head>
<body>
欢迎光临自强学堂
</body>
</html>

  • project的url解析中添加url(r'^$', index, name='home'),

  • 访问http://localhost:8000/,能看到上面的home.html。

客户通过url访问 -> project的url解析 -> 对应的view -> view返回html

2. Django 模板-抽取通用模板 base.html的应用

网站模板的设计,一般的,我们做网站有一些通用的部分,比如 导航,底部,访问统计代码等等,我们将这三个部分抽取出来,作为通用部分.

  • 在templates文件夹下新建:nav.html, bottom.html, tongji.html。

    作为实例,在每个html中输入<h1>☓☓☓</h1>

  • 写一个 base.html 来包含这些通用文件(include)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>[% block title %}默认标题[% endblock%} - 自强学堂</title>
</head>
<body>
[% include 'nav.html'%}

[% block content %}
 <div> 这里是默认部分,如果不覆盖就显示这里的默认内容</div>
[% endblock %}

[% include 'bottom.html'%}
[% include 'tongji.html'%}

</body>
</html>

  • 首页 home.html,继承或者说扩展(extends)原来的 base.html。
[% extends 'base.html' %}
[% block title %} 欢迎光临首页 [% endblock %}

[% block content %}

<h1>这里是首页,欢迎光临</h1>
[% include 'ad.html' %}

[% endblock %}

上面ad.html是广告用页面,需要新建。

  • 访问http://localhost:8000/,能看到的home.html。 image

注意:目前我们将模板文件,全部放在templates文件夹下面,Django会去这个文件夹中查找。但是如果如果每个app中的template都有同样的名称的html呢?这样Django就不一定能找到对应的文件了,因为Django并不能从当前app的文件夹中查找。

3. Django 模板查找机制

Django 模板查找机制: Django 查找模板的过程是在每个 app 的 templates 文件夹中找(而不只是当前 app 中的代码只在当前的 app 的 templates 文件夹中找)。各个 app 的 templates 形成一个文件夹列表,Django 遍历这个列表,一个个文件夹进行查找,当在某一个文件夹找到的时候就停止,所有的都遍历完了还找不到指定的模板的时候就是 Template Not Found (过程类似于Python找包)。这样设计有利当然也有弊,有利是的地方是一个app可以用另一个app的模板文件,弊是有可能会找错了。所以我们使用的时候在 templates 中建立一个 app 同名的文件夹,这样就好了。

  • 把每个app中的 templates 文件夹中再建一个 app 的名称,仅和该app相关的模板放在 app/templates/app/ 目录下面。
zqxt
├── tutorial
│   ├── __init__.py
│   ├── admin.py
│   ├── models.py
│   ├── templates
│   │   └── tutorial
│   │       ├── home.html
│   │       └── search.html
│   ├── tests.py
│   └── views.py
├── learn
│   ├── __init__.py
│   ├── admin.py
│   ├── models.py
│   ├── templates
│   │   └── learn
│   │       ├── home.html
│   │       └── base.html
│   │       └── ad.html
│   │       └── bottom.html
│   │       └── nav.html
│   │       └── tongji.html
│   ├── tests.py
│   └── views.py
├── manage.py
└── zqxt
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

  • 再修改没处引用到html文件的地方,比如将base.html修改为learn\base.html,都是相对于templates目录下的路径。 这样即使html名重复,也能查找到唯一的html文件了。

4. 模板进阶-传递字符/列表/字典到html

  • 传递字符给html
def index(request):
    return render(request, 'learn\home.html',{"mystring":"yes,hello"})
<h1><font color="red">[{mystring}}</font></h1>

最终在页面上能显示出红色的字符串。

  • 传递列表给html
def index(request):
    mylist = ["html","css","js","python"]
    return render(request, 'learn\home.html',{"mylist":mylist})
[% for i in mylist %}
<h1><font color="red">[{i}}</font></h1>
[% endfor %}
  • 传递字典给html
def index(request):
    mydict = {"name":u"lijun","gender":u"male"}
    return render(request, 'learn\home.html',{"mydict":mydict})
[% for key,value in mydict.items %}
<h1><font color="red">[{key}}: [{ value }}</font></h1>
[% endfor %}

或者使用

<h1><font color="red">姓名: [{ mydict.name }}</font></h1>
<h1><font color="red">性别: [{ mydict.gender }}</font></h1>

5. 模板进阶-条件判断与for循环

  • 创建一个长度100的List,并for循环显示
def index(request):
    List = map(str, range(100))  # 一个长度为100的 List
    return render(request, 'learn\home.html',{"List":List})
[% for item in List %}
<font color="red">[{item}},</font>
[% endfor %}

但是上面的显示,会导致每个数字后面都有,分割,显然最后一个字符后面是不需要的。 修改上面的html为如下,如果是最后一个字符用句号,否则用逗号:

[% for item in List %}

<font color="red">[{item}}
  [% if forloop.last %}
    。
  [% else %}
    ,
  [% endif %}
</font>

[% endfor %}
  • 在for循环中还有很多有用的东西,如
变量 描述
forloop.counter 索引从 1 开始算
forloop.counter0 索引从 0 开始算
forloop.revcounter 索引从最大长度到 1
forloop.revcounter0 索引从最大长度到 0
forloop.first 当遍历的元素为第一项时为真
forloop.last 当遍历的元素为最后一项时为真
forloop.parentloop 用在嵌套的 for 循环中,获取上一层 for 循环的 forloop
  • 当列表中可能为空值时用 for empty
<ul>
[% for athlete in athlete_list %}
    <li>[{ athlete.name }}</li>
[% empty %}
    <li>抱歉列表为空</li>
[% endfor %}
</ul>

例如可以这样使用 <font color="red">第[{ forloop.counter}}个元素:[{item}}</font>

6. 模板进阶-得到视图对应的网址

  • 在复习下通过name链接到url,如下代码:
  1. views中添加:
def add(request, a, b):
    c = int(a) + int(b)
    return HttpResponse(str(c))
  1. url解析中添加 url(r'^add/(\d+)/(\d+)/$', add, name='add'),

  2. 模板文件中:

[% for item in List %}
<a href="[% url 'add' item item %}">add me </a>
<font color="red">第[{ forloop.counter}}个元素:[{item}}</font>
[% endfor %}

上述过程,实现点击上面的url后,生成显示的url,并跳转到对应的add view中处理。

  • 给网址取别名,便于多个地方使用,修改html文件
[% url 'add' item item as the_url %}
<a href="[{ the_url }}">   链接到:[{ the_url }}</a>

页面上显示为 链接到:/add/0/0/

7. 模板进阶-逻辑操作

  • ==, !=, >=, <=, >, <,这些逻辑操作符,都可以使用,比如:
[% if num <= 100 and num >= 0 %}
num在0到100之间
[% else %}
数值不在范围之内
[% endif %}

[% if 'ziqiangxuetang' in List %}
自强学堂在名单中
[% endif %}