目前登录,注册和订单页面,都是独立的页面。如果想要有统一的样式,统一的导航栏,那么就需要对每一个页面进行修改,非常麻烦。
可以使用模板继承,Django 模板引擎中最强大(因此也是最复杂)的部分是模板继承。模板继承可以构建基本的“骨架”模板,该模板包含站点的所有常见元素,并定义子模板可以覆盖的块。在 templates 目录下,创建公共模板 base.html,它定义了一个 HTML 骨架文档,将页面分成上中下三栏。子模板使用具体内容填充公共模板中空白块 block。
步骤:
- 创建公共模板
- 创建子模版文件
- 创建和引用静态文件,例如定义样式表文件,图片文件
创建公共模板
公共模板包含了整个页面的框架,一般有公共部分,例如欢迎部分,导航部分,页脚部分,和板块定义。在公共 templates/base.html 中输入以下内容:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width-device-width, initital-scale=1.0">
<link rel="stylesheet" href="{% static 'css/iorder.css' %}">
<title>
{% block title %} 点餐系统 {% endblock %}
</title>
</head>
<body>
<div class="main">
{% block nevbar %}
<div class="nevbar">
<div class="flow-left"><img src="{% static 'img/order.jpg' %}" width="32px" title="点餐"></div>
<div class="flow-left">点餐</div>
<div class="flow-right">登录</div>
<div class="flow-right">注册</div>
<div class="flow-right">退出</div>
</div>
{% endblock %}
{% block section %}
{% endblock %}
{% block footer %}
<div class="footer">
@ 版权信息
</div>
{% endblock %}
</div>
</body>
</html>
{% block 模板块名%},标记所做的是告诉模板引擎子模板可以覆盖模板的那些部分。这里定义了 tilte,nevbar,section,footer 四个 block,可以在子模板中根据需要覆盖这些 block。
此时的导航栏还都没有添加链接。在下一节“11-升级web页面,导航,分页”将会详细介绍。
创建子模版文件
修改 templates/users/login.html 子模板,如下:
{% extends 'base.html' %}
{% block title %}
登陆页面
{% endblock%}
{% block section %}
<div>
<p>登录页面</p>
<p style="color: red;">{{ error }}</p>
<div>
<form action="" method="POST">
{% csrf_token %}
<div>账号: <input type="text" name="username"></div>
<div>密码: <input type="password" name="password"></div>
<div><input type="submit" value="登录"></div>
</form>
</div>
<div><a href="{% url 'users:regist' %}">点击注册</a></div>
</div>
{% endblock%}
{% extend 公共模板 html 文件名 %},需要写在子模板中的开头,表示继承公共模板。它告诉模板引擎该模板“扩展”了另一个模板。模板系统评估该模板时,首先会找到公共模板,也就是 base.html。
{% block 模板块名%},写在公共模板中为可以被继承并重写的内容,写在子模板中为替换公共模板中相同名字的模板块内容。
{% endblock %},标记 block 结束的位置。
修改 templates/users/register.html 子模板,如下:
{% extends 'base.html' %}
{% block title %}
注册页面
{% endblock%}
{% block section %}
<div>
<p>注册页面</p>
<p style="color: red;">{{ error }}</p>
<form action="" method="POST">
{% csrf_token %}
{% if username %}
<div>账号: <input type="text" name="username" value="{{ username }}"></div>
{% else %}
<div>账号: <input type="text" name="username"></div>
{% endif %}
<div>密码: <input type="password" name="password"></div>
<div><input type="submit" value="提交"></div>
</form>
</div>
{% endblock%}
修改 templates/orders/index.html 子模板,如下:
{% extends 'base.html' %}
{% block title %}
订单页面
{% endblock%}
{% block section %}
<div >
<h3>今日 {% now "Y-m-d" %} 订餐订单:</h3>
<table style="display: inline-block; ">
<tr>
<th>编号</th>
<th>姓名</th>
<th>下单时间</th>
<th>菜品</th>
<th>餐馆</th>
<th>数量</th>
<th>辣味</th>
<th>吃饭时间</th>
</tr>
{% for order in order_list %}
<tr>
<td>{{ order.id }}</td>
<td>{{ order.username }}</td>
<td>{{ order.createdate }}</td>
<td>{{ order.dish }}</td>
<td>{{ order.dish.restaurant }}</td>
<td>{{ order.quantity }}</td>
<td>{{ order.get_spicy_display }}</td>
<td>{{ order.get_dinnertime_display }}</td> <!--显示中餐/午餐的value-->
</tr>
{% endfor %}
</table>
</div>
{% endblock%}
定义样式表文件
之前是把样式表定义在了 html 文件中,甚至嵌入到了页面元素中。推荐的做法是,引用第三方的 css 样式表框架,或者将样式都统一放到一个文件中,方便管理和修改。这里在 static/css 目录下,创建样式表文件 iorder.css,将用到的样式都放到给文件里,然后在公共模板 base.html 中引用:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width-device-width, initital-scale=1.0">
<link rel="stylesheet" href="{% static 'css/iorder.css' %}">
<title>
{% block title %} 点餐系统 {% endblock %}
</title>
</head>
{% load static %} 加载在 setting.py 中的STATICFILES_DIRS定义的 static目录。然后在模板中使用load标签来加载 static 标签。
<link rel=“stylesheet” href={%static ‘css/iorder.css’%}> 通过 static 标签加载相应的 css 文件。
同样的方法,也可以加载 Javascript 文件,图片等静态文件。