Template模板

作为Web 框架,Django 需要一种很便利的方法以动态地生成HTML。最常见的做法是使用模板。

模板包含所需HTML 输出的静态部分,以及一些特殊的语法,描述如何将动态内容插入。

模板引擎配置

模板引擎使用该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  % }

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.conf.urls import url
from . import views
urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^list/$', views.goodslist, name='list'),
    url(r'^pwd/$', views.userpwd, name='pwd'),
]

Ajax实战笔记--城市级联操作

1. 项目架构搭建

  • 1.1 创建项目tpdemo,创建应用myapp

      # 创建项目框架tpdemo
      $ django-admin startproject tpdemo
    
      $ cd tpdemo
    
      # 在项目中创建一个myapp应用
      $ python3 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 编辑tpdemo/tpdemo/__init__.py文件,添加Pymysql的数据库操作支持
    import pymysql
    pymysql.install_as_MySQLdb()
  • 1.4 编写项目主路由urls配置,配置对myapp应用路由的访问连接配置: tpdemo/tpdemo/urls.py

from django.conf.urls import include,url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('myapp.urls')),
]
  • 1.5 配置当前应用myapp的路由配置

  • 在myapp应用目录下创建一个路由文件urls.py文件,注意此文件编码为utf-8(建议复制一个)。

  • 编辑应用中的路由配置文件:tpdemo/myapp/urls.py, 内容如下:


from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^$', 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]# python3 manage.py runserver 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
...
    # 城市级联操作
    url(r'^showdistrict$', views.showdistrict, name='showdistrict'), #加载网页
    url(r'^district/([0-9]+)$', 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>
    <script type="text/javascript" src="/static/js/jquery-1.8.2.min.js"></script>
    <script type="text/javascript">
        //编写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);
                    }
                });
            });

        })

    </script>
</head>
<body>
    <h2>Ajax实战笔记--城市级联操作</h2>

    <select id="cid">
        <option>-请选择-</option>
    </select>
</body>
</html>
59
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!