作为一个Web框架,Django需要一种方便的方式来动态生成HTML。最常用的方法依赖于模板。模板包含所需HTML输出的静态部分以及描述如何插入动态内容的特殊语法。
对模板引擎的一般支持和Django模板语言的实现都存在于 django.template 命名空间中
在settings中配置:
# 配置模板
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',# 使用默认的Django的模板
'DIRS': [os.path.join(BASE_DIR, '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',
],
},
},
]
笔记:
get_template
该函数使用给定名称加载模板并返回一个 Template对象,找到第一个匹配的模板即返回
template = get_template('story_detail.html')
Django将要查找的文件,依次为:
示例:
# 最常用的render
from django.shortcuts import render
def my_view(request):
# View code here...
return render(request, 'myapp/index.html', {
'foo': 'bar',
}, content_type='application/xhtml+xml')
# 相当于基础的get_template:
from django.http import HttpResponse
from django.template import loader
def my_view(request):
# View code here...
template = loader.get_template('myapp/index.html')
context = {'foo': 'bar'}
# 注意,这个 render 和 快捷键 render 不是一个对象
return HttpResponse(template.render(context, request), content_type='application/xhtml+xml')
select_template
select_template() 用法类似 get_template() ,除了它需要一个模板名称的列表。它按顺序尝试每个名称并返回存在的第一个模板
template = select_template(['story_253_detail.html','story_detail.html'])
Django将要查找的文件,依次为:
Django模板只是一个文本文档或使用Django模板语言标记的Python字符串。一些结构被模板引擎识别和解释,主要的是变量( {{ 变量 }} )和标签( {% 标签 %} )。
其中也包含模板渲染变量的测试
首先创建一个主应用,子应用。在子应用中创建一个templates文件夹并在下面创建一个template_app文件夹,还有创建一个urls.py路由文件。
配置主应用中的settings
INSTALLED_APPS = [
'template_app',
]
import os
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')],
配置子应用的路由地址(主应用的urls中)
from django.contrib import admin
from django.urls import path
from django.urls.conf import include
urlpatterns = [
path('admin/', admin.site.urls),
path('template_app/', include('template_app.urls'))
]
以上配置基本完成
开始测试模板渲染的变量
子应用url配置
from django.contrib import admin
from django.urls import path
from django.urls.conf import include
from . import views
urlpatterns = [
path('var_test/', views.var_test)
]
子应用的views
from django.shortcuts import render
# Create your views here.
def var_test(request):
# 传递变量给模板
context_name = {
"first_name":'tom',
"last_name":"zhang"
}
return render(request, 'template_app/var_test.html', context_name) # 返回模板携带变量
模板
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
first_name:{{first_name}} <br>
last_name: {{last_name}} <br>
body>
html>
创建数据模型
from django.db import models
# Create your models here.
class Person(models.Model):
pname = models.CharField(max_length=30)
age = models.IntegerField()
password = models.CharField(max_length=8)
sex = models.CharField(max_length=5)
salary = models.FloatField()
配置数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'template_study',
"HOST":'127.0.0.1',
"USER": 'root',
"PASSWORD": 'root',
'PORT':3306
}
}
迁移数据库命令
python manage.py makemigrations template_app
python manage.py migrate template_app
views视图
from django.shortcuts import render
from template_app.models import *
# 在页面中渲染实体_字典_列表
def data_test(request,id):
p = Person.objects.get(pk=id)
person_list = Person.objects.all()
address_dict = {
'bj':'北京',
'sh':'上海',
'gz':'广州'
}
return render(request, 'template_app/data_test.html',{'person':p,'person_list':person_list, 'address_dict':address_dict})
template模板
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>在页面中渲染实体_字典_列表title>
head>
<body>
<p>实体的渲染p>
<ul>
<li>{{ person.pname }}li>
<li>{{ person.age }}li>
<li>{{ person.sex }}li>
<li>{{ person.salary }}li>
ul>
<p>列表的渲染p>
{{ person_list.0.pname }}
{{ person_list.1.pname }}
{{ person_list.2.pname }}
{{ person_list.3.pname }}
{{ person_list.4.pname }}
<p>字典的渲染p>
{{ address_dict.bj }} <br>
{{ address_dict.sh }} <br>
{{ address_dict.gz }} <br>
body>
html>
url
from django.contrib import admin
from django.urls import path
from django.urls.conf import include
from . import views
urlpatterns = [
path('data_test//' , views.data_test)
]
测试代码思路:我们创建一个views视图,然后返回一个模板,内容是form表单的输入账号密码。点击按钮只会,需要跳转到一个登录成功的新路由中。这时候,就需要我们使用csrf_token防跨域攻击
无参数标签 csrf_token ,这个标签是用于html进行 form 表单提交时,包含一个 随机变化的字符串,在html页面中,其实就是一个 inputtype=‘hidden’ 作用是用于防止跨域攻击
{% csrf_token %}
传参的标签 cycle , 参数 ‘odd’ ‘even’ ,空格间隔
标签本身也支持 关键字参数 {% 标签 key1=‘value’ key1=‘even’ %}
{% cycle ‘odd’ ‘even’ %}
代码展示
views
from django.shortcuts import render, HttpResponse
from template_app.models import *
def login_html(request):
return render(request, "template_app/login.html")
def login(request):
return HttpResponse("登录成功")
urls
from django.contrib import admin
from django.urls import path
from django.urls.conf import include
from . import views
urlpatterns = [
path('login_html/',views.login_html),
path('login/',views.login,name="login")
]
template模板—— csrf_token
<body>
<form action="/template_app/login/" method="POST">
{% csrf_token %}
用户名: <input type="text" name="pname"> <br>
密码: <input type="password" name="password"> <br>
<input type="submit" value="登录">
form>
body>
html>
方法概述
输出不是False的第一个参数,所有参数都为False,则什么都不输出
for循环在循环中设置了许多变量:
变量 | 描述 |
---|---|
forloop.counter | 循环的当前迭代(1索引) |
forloop.counter0 | 循环的当前迭代(0索引) |
forloop.revcounter | 循环结束时的迭代次数(1索引) |
forloop.revcounter0 | 循环结束时的迭代次数(0索引) |
forloop.first | 如果这是通过循环的第一次,则为真 |
forloop.last | 如果这是通过循环的最后一次,则为真 |
forloop.parentloop | 对于嵌套循环,这是围绕当前循环的循环 |
views
def login_html(request):
return render(request, "template_app/login.html")
def login(request):
# 从form 表单中获取数据(POST)
data_dict = request.POST
pname = data_dict.get('pname')
password = data_dict.get('password')
# 根据用户名和密码查询人
persons = Person.objects.filter(pname=pname, password=password)
if persons:
# 跳转到Person列表(重定向)
return redirect('find_person')
else:
# 不通过验证,返回登录页面
return render(request,'template_app/login.html')
def find_person(request):
person_list = Person.objects.all()
return render(request,'template_app/person_list.html',{'person_list':person_list})
urls
from django.contrib import admin
from django.urls import path
from django.urls.conf import include
from . import views
urlpatterns = [
path('login_html/',views.login_html),
path('login/',views.login,name="login"),
path('find_person/',views.find_person, name="find_person")
]
templates
<body>
<table>
<tr>
<td>序号td>
<td>姓名td>
<td>年龄td>
<td>性别td>
<td>薪资td>
<td>薪资等级td>
tr>
{% for person in person_list %}
<tr class="{% cycle 'odd' 'even' %}">
<td>{{ forloop.counter }}td>
<td>{{ person.pname }}td>
<td>{{ person.age }}td>
<td>{{ person.sex }}td>
<td>{{ person.salary }}td>
{% if person.salary >= 10000 %}
<td>高新td>
{% elif person.salary >= 5000 %}
<td>中薪td>
{% else %}
<td>低薪td>
{% endif %}
tr>
{% empty %}
没有查询到数据
{% endfor %}
table>
----------firstof{% firstof 0 2 3 %}-------
body>
html>
如何使用应用名? 如何在template中使用a标签跳转路由?如何跳转路由携带参数?
template:login
<body>
<form action="{% url 'template_name:login'%}" method="POST">
{% csrf_token %}
用户名: <input type="text" name="pname"> <br>
密码: <input type="password" name="password"> <br>
<input type="submit" value="登录">
form>
body>
template:person_list
----------url测试标签(跳转的是视图)---------- <br>
<a href="{% url 'template_name:url_test' 10 %}">url测试跳转视图a>
urls
from django.contrib import admin
from django.urls import path
from django.urls.conf import include
from . import views
app_name = "template_name"
urlpatterns = [
path('login_html/',views.login_html),
path('login/',views.login,name="login"),
path('find_person/',views.find_person, name="find_person"),
path('url_test//' , views.url_test, name="url_test")
]
views:
from django.shortcuts import render, HttpResponse, redirect
from template_app.models import *
def login_html(request):
return render(request, "template_app/login.html")
def login(request):
# 从form 表单中获取数据(POST)
data_dict = request.POST
pname = data_dict.get('pname')
password = data_dict.get('password')
# 根据用户名和密码查询人
persons = Person.objects.filter(pname=pname, password=password)
if persons:
# 跳转到Person列表(重定向)
return redirect('template_name:find_person')
else:
# 不通过验证,返回登录页面
return render(request,'template_app/login.html')
def find_person(request):
person_list = Person.objects.all()
return render(request,'template_app/person_list.html',{'person_list':person_list})
def url_test(request,num):
return HttpResponse(f"url测试标签成功!{num}")
widthratio:乘法和除法(具体使用方法笔记写在代码中)
with:简单的名称缓存复杂变量,当访问多次耗时的方法(例如操作数据库的方法):
<body>
<table>
<tr>
<td>序号td>
<td>姓名td>
<td>年龄td>
<td>性别td>
<td>薪资td>
<td>薪资等级td>
<td>年薪td>
<td>年薪调用方法td>
<td>width的使用td>
tr>
{% for person in person_list %}
<tr class="{% cycle 'odd' 'even' %}">
<td>{{ forloop.counter }}td>
<td>{{ person.pname }}td>
<td>{{ person.age }}td>
<td>{{ person.sex }}td>
<td>{{ person.salary }}td>
{% if person.salary >= 10000 %}
<td>高新td>
{% elif person.salary >= 5000 %}
<td>中薪td>
{% else %}
<td>低薪td>
{% endif %}
<td>{% widthratio person.salary 1 12 %}td>
<td>{{ person.year_salary }}td>
<td>
{% with new_age=person.age %}
{{ new_age }}
{% endwith %}
td>
tr>
{% empty %}
没有查询到数据
{% endfor %}
模型model
from django.db import models
# Create your models here.
class Person(models.Model):
pname = models.CharField(max_length=30)
age = models.IntegerField()
password = models.CharField(max_length=8)
sex = models.CharField(max_length=5)
salary = models.FloatField()
def year_salary(self):
return self.salary * 12
<body>
-----------length(计算字符串长度)------------------ <br>
msg:{{msg|length}} <br>
{% if msg|length >= 10 %}
msg的长度大于等于10 <br>
{%endif%}
-----------add(加法)--------------------- <br>
num+10:{{num|add:"10"}} <br>
-----------divisibleby(是否能整除于num)--------------------- <br>
{{ num|divisibleby:"2" }} <br>
-----------addslashes(单引号前加\)--------------------- <br>
{{ value|addslashes }} <br>
-----------capfirst(首字母大写)--------------------- <br>
{{ msg|capfirst }} <br>
-----------center(将值置于给定宽度的字段中)--------------------- <br>
{{ msg|center:"50" }} <br>
-----------cut(去掉对应的值)--------------------- <br>
{{ value|cut:" " }} <br>
-----------日期时间--------------------- <br>
{{ birthday }}
{{ value|date:"Y-m-d H:i:s" }}
body>
主template
<body>
{% include "template_app/header.html" with name='测试是否会覆盖视图传递的数据' only %}
{% include "template_app/footer.html" %}
body>
header
<body>
<ul>
<li>新闻li>
<li>娱乐li>
<li>热点li>
<li>{{name}}li>
<li>{{age|default:18}}li>
ul>
body>
footer
<body>
<p>关于百度About Baidu使用百度前必读帮助中心企业推广京公网安备11000002000001号京ICP证030173号信息网络传播视听节目许可证p>
body>
views
def include_test(request):
return render(request, 'template_app/include_test.html',{"name":"关注",'age':30})
DOCTYPE html>
<html lang="en">
{% load static %}
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<link rel="stylesheet" href="{% static 'template_app/css/mystyle.css' %}">
<script type="text/javascript" src="{% static 'template_app/js/js_test.js' %}">script>
head>
<body>
<p>静态文件测试p>
<p class="pstyle">显示图片p>
<img src="{% static 'template_app/imgs/1.jpg' %}">
<button onclick="click_func()">点我button>
body>
html>
Django模板引擎中最强大,也是最复杂的部分是模板继承。模板继承允许构建一个基本“骨架”模板,其中包含您网站的所有常见元素,并定义子模板可以覆盖的 blocks
继承的技巧:
{% extends "template_app/base.html" %}
{% block title %}
extends_testhtml
{% endblock %}
{% load static %}
{% block css %}
<link rel="stylesheet" href="{% static 'template_app/css/mystyle.css' %}">
{%endblock%}
{% block js %}
<script type="text/javascript" src="{% static 'template_app/js/js_test.js' %}">script>
{% endblock %}
{% block context %}
<p class="pstyle">样式测试p>
<button onclick="click_func()">点击button>
{% endblock %}
父模板
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}basehtml{% endblock %}title>
{% block css %}{%endblock%}
{% block js %}{%endblock%}
head>
<body>
{% include "template_app/header.html" with name="模板继承base.html" %}
{%block context%}{%endblock%}
{% include "template_app/footer.html" %}
body>
html>