Django模板
在项目迭代流程中,前端页面都会进行大量的修改,如果将页面放到视图函数中,那么当对前端页面修改的时候,也会使得视图函数发生变化,大大加重了后端的负担。从 MTV 设计模式的角度出发,视图层是实现业务逻辑的,在视图层编写代码和编写 HTML 页面是两项可以相互独立的工作。
在 Django 中我们把 “模板” 称之为 Template,是设计模式中的 T 层,模板用于编写html代码,还可以嵌入模板代码转换更方便的完成页面开发,再通过在视图中渲染模板,将生成模板的设计实现了业务逻辑视图与显示内容模板的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用。
模板系统的配置
其实 T 层应用是这样实现的,当创建好一个 Django 项目后,在项目的同级目录下(或在应用目录下)创建一个名为 templates 文件夹,对它进行简单的配置后,这个文件夹将被 Django 自动识别。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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',
],
},
},
]
TEMPLATES 变量内容解析:
- BACKEND : Django默认设置,指定了要是用的模板引擎的 Python 路径;
- DIRS : 一个目录列表,指定模板文件的存放路径,可以是一个或者多个。模板引擎将按照列表中定义的顺序查找模板文件;
- APP_DIRS : 一个布尔值,默认为 Ture,表示会在安装应用中的 templates 目录中搜索所有模板文件;当值为 Ture时,可不用在DIRS参数中添加在应用中的templstes文件夹
- OPTIONS : 指定额外的选项,不同的模板引擎有着不同的可选参数。
# 一般情况下,是直接在项目根目录下创建templates文件夹,设置 TEMPLATES 的 DIRS 值则为
'DIRS': [os.path.join(BASE_DIR,'templates')]
# dirs为空时,默认的templates位置为app下
'DIRS': []
模板响应
html内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板响应</title>
</head>
<body>
<h1>第一次模板响应</h1>
</body>
</html>
views视图函数
from django.shortcuts import render
def home(request):
return render(request, 'equipment/home.html')
urls配置
from django.urls import path
from . import views
app_name = 'equipment'
urlpatterns = [
path('home/', views.home, name='home'),
]
主路由配置
from django.urls import path, include
urlpatterns = [
path('equip/', include('equipment.urls')),
]
响应内容
模板传参
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板响应传参</title>
</head>
<body>
<h1>第一次模板响应{{info}}</h1>
</body>
</html>
模板传参:
第一次模板响应{{info}}
中使用{{}}括起来的内容是一个模板的变量,其中event_list是变量名,用于接收视图函数中传递的数据views视图
def home(request):
info = "Hello World!!"
return render(request, 'equipment/home.html', context={'info': info})
带参数响应
render方法: render 是 View 层加载模板的一种方式,它封装在 django.shortcuts 模块中,它的作用是结合一个给定的模板和一个给定的字典,并返回一个渲染后的 HttpResponse 对象。通俗的讲就是把字典格式的内容, 加载进 templates 目录中定义的 HTML 文件, 最终通过浏览器渲染呈现。
render(request, template_name, context=None, content_type=None, status=None, using=None)
render方法参数解析:
request: 是一个固定参数,用于生成响应的请求对象;
template_name: templates 中定义的文件, 要注意路径名. 比如html文件所在路径为 templates\home\index.html, 参数就要写home\index.html;
context: 要传入文件中用于渲染呈现的数据, 默认是字典格式;内容为{‘模板变量’:视图函数变量}
content_type: 生成的文档要使用的媒体格式类型。默认为 DEFAULT_CONTENT_TYPE 设置的值;
status: http 的响应代码,默认是 200;
using: 用于加载模板使用的模板引擎的名称。
request、template_name、context为必传参数
模板语法
模板分为静态部分和动态部分,其中动态部分主要就是模板语言,下面通过模板变量、标签、过滤器、注释几个方面进行说明。
模板变量
通过后端传递在前端html页面当中通过模板语法获取变量的值
from django.shortcuts import render
def hello(request):
text = "Hello World !"
return render(request, 'equipment/hello.html', context={"text": text})
设置路由
from django.urls import path
from . import views
app_name = 'equipment'
urlpatterns = [
path('hello/', views.hello, name='hello'),
]
在equipment/templates/equipment当中创建hello.html文件,编写内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<h1 style="text-align: center; color: crimson">{{ text }}</h1>
</body>
</html>
效果展示
标签
模板中的常见标签有for、if、比较运算符、布尔运算符等
for语法的使用
from django.shortcuts import render
def goods_list(request):
shop_list = [
{'id': 1, 'name': '华为P60Pro焕彩紫', 'cate': '手机', 'memory': '8G', 'rom': '128G', 'price': '5499.00'},
{'id': 2, 'name': '华为P60天空蓝手机', 'cate': '手机', 'memory': '8G', 'rom': '256G', 'price': '5699.00'},
{'id': 3, 'name': '华为Meta60手机', 'cate': '手机', 'memory': '12G', 'rom': '512G', 'price': '6999.00'},
]
return render(request, 'equipment/goods.html', context={'goods_list': shop_list})
设置路由
from django.urls import path
from . import views
app_name = 'equipment'
urlpatterns = [
path('goods_list/', views.goods_list, name='goods_list'),
]
在equipment/templates/equipment下创建goods_list.html文件,添加内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>手机信息展示页面</title>
</head>
<body>
<div style="width: 80%; margin: 50px auto; text-align: center">
<table border="1" style="text-align: center; width: 100%; " >
<tr >
<th>编写</th>
<th>名称</th>
<th>内存</th>
<th>存储</th>
<th>价格</th>
<th>分类</th>
</tr>
{% for goods in goods_list %}
<tr >
<td>{{ goods.id }}</td>
<td>{{ goods.name }}</td>
<td>{{ goods.memory }}</td>
<td>{{ goods.rom }}</td>
<td>{{ goods.price }}</td>
<td>{{ goods.cate }}</td>
</tr>
{% endfor %}
</table>
</div>
</body>
</html>
效果展示
if语句
隔行变色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>手机信息展示页面</title>
</head>
<body>
<div style="width: 80%; margin: 50px auto; text-align: center">
<table border="1" style="text-align: center; width: 100%; " >
<tr >
<th>编写</th>
<th>名称</th>
<th>内存</th>
<th>存储</th>
<th>价格</th>
<th>分类</th>
</tr>
{% for goods in goods_list %}
{% if forloop.counter|divisibleby:"2" %}
<tr style="background:gray">
{% else %}
<tr>
{% endif %}
<td>{{ goods.id }}</td>
<td>{{ goods.name }}</td>
<td>{{ goods.memory }}</td>
<td>{{ goods.rom }}</td>
<td>{{ goods.price }}</td>
<td>{{ goods.cate }}</td>
</tr>
{% endfor %}
</table>
</div>
</body>
</html>
效果展示
过滤器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>手机信息展示页面</title>
</head>
<body>
<div style="width: 80%; margin: 50px auto; text-align: center">
<table border="1" style="text-align: center; width: 100%;" >
<tr >
<th>编写</th>
<th>名称</th>
<th>内存</th>
<th>存储</th>
<th>价格</th>
<th>分类</th>
<th>发布日期</th>
</tr>
{% for goods in goods_list %}
{% if forloop.counter|divisibleby:"2" %}
<tr style="background:gray">
{% else %}
<tr>
{% endif %}
<td>{{ goods.id }}</td>
<td>{{ goods.name }}</td>
<td>{{ goods.memory }}</td>
<td>{{ goods.rom }}</td>
<td>{{ goods.price }}</td>
<td>{{ goods.cate }}</td>
<td>{{ goods.pub_date | date:'Y-m-d' }}</td>
</tr>
{% endfor %}
{% comment %}
多行注释,在这里编写注释内容
{% endcomment %}
{# <h1></h1>#}
</table>
</div>
</body>
</html>
效果展示
自定义过滤器
自定义过滤器,处理价格,在价格的前后分别加上字符: ¥ 和 元
在app的目录下,创建templatetags文件夹,文件夹中要有__init__.py
文件。
创建过滤器的文件时要以filter_name的形式进行。如处理价格: filter_price.py
from django.template import Library
# 创建Library对象
register = Library()
# 使用装饰器进行处理,定义求余函数filterid(),将num对2求余
@register.filter()
def filter_price(num):
return f"¥{num}元"
在html当中使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>手机信息展示页面</title>
</head>
<body>
<div style="width: 80%; margin: 50px auto; text-align: center">
{% load filter_price %}
<table border="1" style="text-align: center; width: 100%;" >
<tr >
<th>编写</th>
<th>名称</th>
<th>内存</th>
<th>存储</th>
<th>价格</th>
<th>分类</th>
<th>发布日期</th>
</tr>
{% for goods in goods_list %}
{% if forloop.counter|divisibleby:"2" %}
<tr style="background:gray">
{% else %}
<tr>
{% endif %}
<td>{{ goods.id }}</td>
<td>{{ goods.name }}</td>
<td>{{ goods.memory }}</td>
<td>{{ goods.rom }}</td>
<td>{{ goods.price | filter_price}}</td>
<td>{{ goods.cate }}</td>
<td>{{ goods.pub_date | date:'Y-m-d' }}</td>
</tr>
{% endfor %}
{% comment %}
多行注释,在这里编写注释内容
{% endcomment %}
{# <h1></h1>#}
</table>
</div>
</body>
</html>
效果展示
模板继承
继承模板主要是为了提高代码重用性或减少代码冗余率,以减少开发人员的工作量。
在templates下先创建个base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %} {% endblock %}</title>
{% block css %}
{% endblock %}
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
子模板创建,并继承父模板
在equipment/templates/equipment/pages/目录下创建login.html文件,编写内容如下:
{% extends 'equipment/base.html' %}
{% block title %} 用户登录页面 {% endblock %}
{% block css %}
<style>
.login_div {
margin: 150px auto;
text-align: center;
}
</style>
{% endblock %}
{% block content %}
<div class="login_div">
<form action="" method="post">
<p>姓名: <input type="text"></p>
<p>密码: <input type="text"></p>
<p><input type="submit" value="登录"></p>
</form>
</div>
{% endblock %}
编写views视图,对页面进行渲染
from django.shortcuts import render
def login(request):
return render(request, 'equipment/pages/login.html')
编写路由
from django.urls import path
from . import views
app_name = 'equipment'
urlpatterns = [
path('login/', views.login, name='login'),
]
效果展示
模板传参
post提交表单
views.py视图
from django.contrib.auth.hashers import make_password, check_password
from django.shortcuts import render
from django.views import View
from equipment.models import User
class RegisterView(View):
def get(self, request):
return render(request, 'equipment/register.html')
def post(self, request):
username = request.POST.get('username')
password1 = request.POST.get('password1')
password2 = request.POST.get('password2')
email = request.POST.get('email')
if password1 != password2:
return render(request, 'equipment/register.html', context={'message': '两次密码不一致!'})
user_obj = User.objects.filter(username=username).first()
if user_obj:
return render(request, 'equipment/register.html', context={'message': '用户已存在!'})
User.objects.create(username=username, password=make_password(password1), email=email)
return render(request, 'equipment/register.html', context={'message': '用户注册成功!'})
class LoginView(View):
"""
登录视图
"""
def get(self, request):
return render(request, 'equipment/login.html')
def post(self, request):
"""
用户登录
"""
username = request.POST.get('username')
password = request.POST.get('password')
user_obj = User.objects.filter(username=username).first()
if user_obj is None:
return render(request, 'equipment/login.html', context={'message': '用户不存在'})
if check_password(password, user_obj.password):
return render(request, 'equipment/index.html', context={'username': user_obj.username})
else:
return render(request, 'equipment/login.html', context={'message': '密码不正确'})
路由配置
from django.urls import path
from . import views
app_name = 'equipment'
urlpatterns = [
path('register/', views.RegisterView.as_view(), name='register'),
path('login/', views.LoginView.as_view(), name='login'),
]
html页面
bash页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %} {% endblock %}</title>
{% block css %}
{% endblock %}
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
register
{% extends 'equipment/base.html' %}
{% block title %} 注册页面 {% endblock %}
{% block css %}
<style>
.register_div {
margin: 150px auto;
text-align: center;
}
</style>
{% endblock %}
{% block content %}
<div class="register_div">
<form action="{% url 'equipment:register' %}" method="post">
{% csrf_token %}
<p>用 户 名:<input type="text" name="username"></p>
<p>密  码:<input type="password" name="password1"></p>
<p>确认密码:<input type="password" name="password2"></p>
<p><input type="submit" value="注册"> <a href="{% url 'equipment:login' %}">有账号,去登录</a></p>
</form>
</div>
{% endblock %}
login页面
{% extends 'equipment/base.html' %}
{% block title %} 登录页面 {% endblock %}
{% block css %}
<style>
.login_div {
margin: 150px auto;
text-align: center;
}
</style>
{% endblock %}
{% block content %}
<div class="login_div">
<form action="{% url 'equipment:login' %}" method="post">
{% csrf_token %}
<p>用户名:<input type="text" name="username"></p>
<p>密 码:<input type="password" name="password"></p>
<p><input type="submit" value="登录">   <a href="{% url 'equipment:register' %}">没有账号,去注册</a></p>
</form>
</div>
{% endblock %}
index页面
{% extends 'equipment/base.html' %}
{% block title %} 首页 {% endblock %}
{% block content %}
<h1>首页展示</h1>
{% endblock %}
页面效果展示