目录
一、Django的模板介绍
模板引擎配置
二、模板语法
1.变量
2.标签
3.过滤器
4.注释
5.模板运算
6.自定义 标签 或 过滤器
三、模板继承
三层继承结构
四、Ajax实战笔记--城市级联操作
1. 项目架构搭建
2. 开发《城市级联信息操作》
一、Django的模板介绍
- 作为Web 框架,Django 需要一种很便利的方法来动态地生成HTML。
- 常见做法是使用模板python画流程图。 模板包含所需HTML 输出的静态部分,以及一些特殊的语法,描述如何将动态内容插入。
- 模板任务就是输出数据,输出方式:直接输出,过滤输出、判断输出,循环输出
- 在Django框架中如何使用模板:
1. 在项目的settings.py配置文件中配置模板目录
'DIRS': [os.path.join(BASE_DIR,'templates')],
2. 在应用的视图文件加载模板,并放置要输出的数据
return render(request,“目录/模板文件.html”,{放置字典数据})
3. 在模板文件中使用变量、标签和过滤器等输出信息
{{ 变量 }} {% 标签 %} {{ 变量|过滤器 }}
模板引擎配置
模板引擎使用该TEMPLATES设置进行配置。这是一个配置列表,每个引擎一个。
默认值为空。在 settings.py由所产生的startproject命令定义一个更有用的值:
在做下面模板配置的同时,也要在项目的根目录下创建一个
templates
目录
# 项目目录下的settings.py配置文件添加TEMPLATES中的DIRS配置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'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',
],
},
},
]
二、模板语法
1.变量
- 变量输出语法
{{ var }}
- 当模版引擎遇到一个变量,将计算这个变量,然后将结果输出
- 变量名必须由字母、数字、下划线(不能以下划线开头)和点组成
- 当模版引擎遇到点("."),会按照下列顺序查询:
- 字典查询,例如:foo["bar"]
- 属性或方法查询,例如:foo.bar
- 数字索引查询,例如:foo[bar]
- 如果变量不存在, 模版系统将插入'' (空字符串)
- 在模板中调用方法时不能传递参数
2.标签
- 语法
{% tag %}
- 作用
- 在输出中创建文本
- 控制循环或逻辑
- 加载外部信息到模板中
for标签
{% for ... in ... %}
循环逻辑
{% endfor %}
if标签
{% if ... %}
逻辑1
{% elif ... %}
逻辑2
{% else %}
逻辑3
{% endif %}
例:
{% if vo.state == 0 %}
管理员
{% elif vo.state == 1 %}
VIP账户
{% else %}
<span style="color:red">禁用账户</span>
{% endif %}
comment标签
{% comment %}
多行注释
{% endcomment %}
include:加载模板并以标签内的参数渲染
{% include "base/index.html" %}
url:反向解析
{% url 'name' p1 p2 %}
csrf_token:这个标签用于跨站请求伪造保护
{% csrf_token %}
3.过滤器
- 语法:
{{ 变量|过滤器 }},例如{{ name|lower }},表示将变量name的值变为小写输出
- 使用管道符号 (|)来应用过滤器
- 通过使用过滤器来改变变量的计算结果
- 关闭HTML自动转义
{{ data|safe }}
- 可以在if标签中使用过滤器结合运算符
if list1|length > 1
- 过滤器能够被“串联”,构成过滤器链
name|lower|upper
- 过滤器可以传递参数,参数使用引号包起来
list|join:", "
- default:如果一个变量没有被提供,或者值为false或空,则使用默认值,否则使用变量的值
value|default:"什么也没有"
- date:根据给定格式对一个date变量格式化
value|date:'Y-m-d'
4.注释
- 单行注释
{# 注释 #}
- 多行注释
{% comment %}
多行注释
{% endcomment %}
这个注释是在网页上源代码里也看不到的
5.模板运算
- 加
{{ value|add:10 }}
note:value=5,则结果返回15
- 减
{{ value|add:-10 }}
note:value=5,则结果返回-5,加一个负数就是减法了
- 乘
{% widthratio 5 1 100 %}
note:等同于:(5 / 1) * 100 ,结果返回500,
withratio需要三个参数,它会使用参数1/参数2*参数3的方式进行运算,进行乘法运算,使「参数2」=1
- 除
{% widthratio 5 100 1 %}
note:等同于:(5 / 100) * 1,则结果返回0.05,和乘法一样,使「参数3」= 1就是除法了。
6.自定义 标签 或 过滤器
- 首先在当前应用目录下创建一个
templatetags
模板标签目录,建议内放一个__init__.py
的空文件 - 然后在
templatetags
目录下创建一个模板标签文件pagetag.py(这个名字随意取)
,具体代码如下:
templatetags
├── pagetag.py
----------------pagetag.py-------------------------
from django import template
register = template.Library()
# 自定义过滤器(实现大写转换)
@register.filter
def myupper(val):
# print ('val from template:',val)
return val.upper()
# 自定义标签(实现减法计算)
#from django.utils.html import format_html
@register.simple_tag
def jian(a,b):
res = int(a) - int(b)
return res
- 使用:在模板文件使用
{% load pagetag %}
<h4>6. 自定义标签 </h4>
{% load pagetag %}
大写:{{name|myupper}} <br/>
相减:{% jian m1 m2 %}
三、模板继承
- 模板继承可以减少页面内容的重复定义,实现页面内容的重用
- 典型应用:网站的头部、尾部是一样的,这些内容可以定义在父模板中,子模板不需要重复定义
- block标签:在父模板中预留区域,在子模板中填充
- extends继承:继承,写在模板文件的第一行
- 定义父模板base.html
{ % block block_name % }
这里可以定义默认值
如果不定义默认值,则表示空字符串
{ % endblock % }
- 定义子模板index.html
{ % extends "base.html" % }
- 在子模板中使用block填充预留区域
{ % block block_name % }
实际填充内容
{ % endblock % }
说明
- 如果在模版中使用extends标签,它必须是模版中的第一个标签
- 不能在一个模版中定义多个相同名字的block标签
- 子模版不必定义全部父模版中的blocks,如果子模版没有定义block,则使用了父模版中的默认值
- 如果发现在模板中大量的复制内容,那就应该把内容移动到父模板中
- 使用可以获取父模板中block的内容
- 为了更好的可读性,可以给endblock标签一个名字
{ % block block_name % }
区域内容
{ % endblock block_name % }
三层继承结构
- 三层继承结构使代码得到最大程度的复用,并且使得添加内容更加简单
1.创建根级模板
- 名称为“base.html”
- 存放整个站点共用的内容
<!DOCTYPE html>
<html>
<head>
<title>{ % block title % }{ % endblock % } 水果超市</title>
</head>
<body>
top--{{logo}}
<hr/>
{ % block left % }
{ % endblock % }
{ % block content % }
{ % endblock % }
<hr/>
bottom
</body>
</html>
2.创建分支模版
- 继承自base.html
- 名为“base_*.html”
- 定义特定分支共用的内容
- 定义base_goods.html
{ % extends 'temtest/base.html' % }
{ % block title % }商品{ % endblock % }
{ % block left % }
<h1>goods left</h1>
{ % endblock % }
- 定义base_user.html
{ % extends 'temtest/base.html' % }
{ % block title % }用户中心{ % endblock % }
{ % block left % }
<font color='blue'>user left</font>
{ % endblock % }
- 定义index.html,继承自base.html,不需要写left块
{ % extends 'temtest/base.html' % }
{ % block content % }
首页内容
{ % endblock content % }
3.为具体页面创建模板,继承自分支模板
- 定义商品列表页goodslist.html
{ % extends 'temtest/base_goods.html' % }
{ % block content % }
商品正文列表
{ % endblock content % }
- 定义用户密码页userpwd.html
{ % extends 'temtest/base_user.html' % }
{ % block content % }
用户密码修改
{ % endblock content % }
4.视图调用具体页面,并传递模板中需要的数据
- 首页视图index
logo='welcome to itcast'
def index(request):
return render(request, 'temtest/index.html', {'logo': logo})
- 商品列表视图goodslist
def goodslist(request):
return render(request, 'temtest/goodslist.html', {'logo': logo})
- 用户密码视图userpwd
def userpwd(request):
return render(request, 'temtest/userpwd.html', {'logo': logo})
5.配置url
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('list/', views.goodslist, name='list'),
path('pwd/', views.userpwd, name='pwd'),
]
四、Ajax实战笔记--城市级联操作
- Ajax = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
- Ajax 不是新的编程语言,而是一种使用现有标准的新方法。
- Ajax 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
1. 项目架构搭建
- 1.1 创建项目tpdemo,创建应用myapp
# 创建项目框架tpdemo
$ django-admin startproject tpdemo
$ cd tpdemo
# 在项目中创建一个myapp应用
$ python manage.py startapp myapp
# 创建模板目录
$ mkdir templates
$ mkdir templates/myapp
$ cd ..
$ tree tpdemo
tpdemo
├── tpdemo
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
├── myapp
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── templates
└── mytest
- 1.2 编辑tpdemo/tpdemo/settings.py文件,配置数据库连接
...
#配置自己的服务器IP地址
ALLOWED_HOSTS = ['*']
...
#添加自己应用
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp',
]
...
# 配置模板路径信息
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'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',
],
},
},
]
...
# 数据库连接配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mytest',
'USER': 'root',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '3306',
}
...
- 1.3 Django使用MySQL数据库需要加载 MySQLdb模块,需要安装 mysqlclient,若已经安装请略过。
pip install mysqlclient
- 1.4 编写项目主路由urls配置,配置对myapp应用路由的访问连接配置: tpdemo/tpdemo/urls.py
from django.urls import include,path
from django.contrib import admin
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('myapp.urls')),
]
- 1.5 配置当前应用myapp的路由配置
- 在myapp应用目录下创建一个路由文件urls.py文件,注意此文件编码为utf-8(建议复制一个)。
- 编辑应用中的路由配置文件:tpdemo/myapp/urls.py, 内容如下:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name="index"),
]
- 1.6 编写视图tpdemo/myapp/views.py
from django.shortcuts import render
from django.http import HttpResponse
# 网站首页
def index(request):
return render(request,'myapp/index.html')
- 1.7 定义模板并编写模板 tpdemo/templates/myapp/index.html
<!DOCTYPE html>
<html lang="cn">
<head>
<meta charset="UTF-8">
<title>Django框架案例</title>
</head>
<body>
<h2>Django框架案例</h2>
<h4><a href="#">1. Ajax实战笔记--城市级联操作</a></h4>
</body>
</html>
- 1.8 启动服务,通过浏览器测试效果
[root@localhost tpdemo]# ls
tpdemo manage.py myapp templates
[root@localhost tpdemo]# python manage.py runserver 0.0.0.0:8000
- 打开浏览器输入网址:http://localhost:8000
2. 开发《城市级联信息操作》
- 2.1 将提前准备好的district.sql信息导入到mydb数据库中
在mydb数据库中存在一个district(城市区县信息表) - 2.2 编写model类:打开tpdemo/myapp/models.py文件
from django.db import models
# 自定义城市区县信息model类
class District(models.Model):
name = models.CharField(max_length=255)
upid = models.IntegerField()
class Meta:
db_table = "district" # 指定真实表名
- 2.3 编写子路由文件:tpdemo/myapp/urls.py
...
# 城市级联操作
path('showdistrict/', views.showdistrict, name='showdistrict'), #加载网页
path('district/<int:upid>', views.district, name='district'), #Ajax加载城市信息
...
- 2.4 编写视图文件:tpdemo/myapp/views.py
from django.http import HttpResponse,JsonResponse
from myapp.models import District
...
# 加载城市级联信息操作模板
def showdistrict(request):
return render(request,"myapp/district.html")
# 加载对应的城市信息,并json格式ajax方式响应
def district(request,upid):
dlist = District.objects.filter(upid=upid)
list = []
for ob in dlist:
list.append({'id':ob.id,'name':ob.name})
return JsonResponse({'data':list})
...
- 启动服务测试:url:http://localhost:8000/district/0 加载一级城市信息
- 2.5 开发网页前端的准备:首先启用静态资源目录
- 在项目的根目录下创建一个静态资源目录:static 路径:tpdemo/static
- 并在此目录下创建一个js目录。然后将jquery文件:jquery-1.8.2.min.js放到此目录中 具体位置:tpdemo/static/js/jquery-1.8.2.min.js
- 编辑tpdemo/tpdemo/settings.py配置文件,在最后加入代码:(配置静态资源目录)
...
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static'),
]
- 2.6 配置访问url:编辑tpdemo/templates/myapp/index.html
...
<h4><a href="{% url 'showdistrict' %}">1. Ajax实战笔记--城市级联操作</a></h4>
...
- 2.7 定义并编写模板文件:tpdemo/templates/myapp/district.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ajax实战--城市级联操作</title>
< type="text/java" src="/static/js/jquery-1.8.2.min.js"></>
< type="text/java">
//编写js代码
$(function(){
$.ajax({
type:'get',
url:"{% url 'district' 0 %}",
dataType:'json',
async: false,
success:function(res){
list = res.data;
//遍历响应的城市信息
for(var i=0;i<list.length;i++){
$("#cid").append("<option value='"+list[i].id+"'>"+list[i].name+"</option>");
}
},
});
//获取最后一个下拉框并添加选中事件
$("select").live('change',function(){
//获取选中的id号
var id = $(this).val();
$(this).nextAll().remove();
$.ajax({
url: "/district/"+id,
type: 'get',
data: {},
dataType:'json',
success:function(res){
if(res.data.length<1)
return;
var data = res.data;
var select = $("<select></select>")
for(var i=0;i<data.length;i++){
$('<option value="'+data[i].id+'">'+data[i].name+'</option>').appendTo(select)
//$('select:last').append('<option value="'+data[i].id+'">'+data[i].name+'</option>');
}
$("select:last").after(select);
}
});
});
})
</>
</head>
<body>
<h2>Ajax实战笔记--城市级联操作</h2>
<select id="cid">
<option>-请选择-</option>
</select>
</body>
</html>