一:   什么是模板?模板的作用?

二:模板的查找路径的配置

三:常用的模板的语法

四:常用的模板过滤器

五:自定义模板过滤器

六:引入模板

七:模板的继承

八:加载静态文件

 

一:什么是模板,模板的作用

  模板就是一种带有特殊语法的html文件,它能够把表现形式和数据分离开来,然后通过视图返回给浏览器。

二:模板的查找路径:

  在项目的setting.py文件中,有个TEMPLATES的配置,这是一个列表,列表中的每一项都是一个字典类型;这个配置包含了模板引擎的配置,模板查找的路径配置,模板的上下文的配置等。

  查找顺序:先在DIRS路径中查找,找到了就返回,没有找到就去APP_DIRS路径中查找

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',     #BACKEND:表示django使用的模板类型(DjangoTemplates)还有一种Jinja2类型
        'DIRS': [os.path.join(BASE_DIR, 'templates')]           #DIRS:这里存放的是所有的模板路径,视图渲染的时候会先从这里开始查找(这里可以放一些公共的模板)
        ,
        'APP_DIRS': True,   #APP_DIRS设置为True表示,当上面的DIRS没有找到模板的时候再从每个APP中查找
        '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',
            ],
        },
    },
]

三常用的模板语法:

  常见的两种类型:变量 {{  }},逻辑:{% %}

  {{var}}标量标签;{% if ...%}逻辑标签;{{aaa|bbb}}过滤器标签

  1变量:

    视图函数在使用render或者render_to_string的时候可以传递一个context参数,这个参数是一个字典类型,模板中的变量就是从这个字典中读取。

    模板代码:{{username}}

    视图代码:return render(request,"index.html",context={"username":"xiaoming"})

    模板中也支持点(.)的形式获取值:

view.py代码:

from django.http import HttpResponse
from django.template.loader import render_to_string
from django.shortcuts import redirect,reverse,render
class Person(object):              #定义一个Person类
    def __init__(self,username,age):
        self.username = username
        self.age = age

def index(request):
    person1 = Person("小红",22)
    person2 = Person("小黑",18)
    person3 = Person("大黄",80)
    Persons = [person1,person2,person3]   #把三个人放到一个列表中
    context={
        "persons":Persons,   #传递的参数是一个列表(也可以是元组)
        "books":"红楼梦",    #传递的参数是一个变量
        "car":{        传递的参数是一个字典
            "brand":"宝马",
            "price":"88万",
        }
    }
    return render(request,"index.html",context=context)

html代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  #模板中都是以.的形式获取
  #如果是一个字典,则获取key对应的值;如果是一个对象,则获取对应的属性或方法,如果是一个列表(元组)通过list.1的方式获取 {{ books }}<br> {{ car.brand }}<br> {{ persons.2.age }}<br> {{ persons.1.username }} </body> </html>

  2常用标签:{% 标签%}

    if标签:相当于python中的if,有else,elif相对应,可以使用<,>,<=,>=,==,!=,in,not in ,is,is not等判断运算符

def index(request):
    context={
        "person":{
            "age":20
        },
        "books":[
            "红楼梦",
            "水浒传",
            "三国演义",
            "西游记"
        ]
    }
    return render(request,"index.html",context=context)
{% if person.age > 40 %}    #有if标签就有相对应的endif标签结尾,代码写在之间
    <p>大于40岁</p>
{% elif person.age < 18%}
    <p>大于18岁</p>
{% else %}
    <p>18岁到20岁之间</p>
{% endif %}


{% if "西游记" not in books %}
    <p>不在四大名著之中</p>
{% else %}
    <p>在四大名著之中</p>
{% endif %}

    for...in..标签:可以遍历列表,元组,字典,字符串等一切可以遍历的对象

    遍历字典的时候需要用到items,key,value

    DTL中提供了一些变量可以使用:

    forloop.counter:当前循环的下标,以1开始

    forloop.counter0:当前循环的下标,以0开始

    forloop.revcounter:当前循环的反向下标(1)

    forloop.revcounter0:当前循环的反向下标(0)

    forloop.first:是否是第一次遍历

    forloop.last: 是否是最后一次遍历

def index(request):
    context={
        "person":{
            "age":20,
            "name":"小黑",
            "sex":""
        },
        "books":[
            {
                'name': '三国演义',
                'author': '罗贯中',
                'price': 99
            },
            {
                'name': '水浒传',
                'author': '施耐庵',
                'price': 89
            },
            {
                'name': '西游记',
                'author': '吴承恩',
                'price': 79
            },
            {
                'name': '红楼梦',
                'author': '曹雪芹',
                'price': 120
            }
        ],
    }
    return render(request,"index.html",context=context)

html代码:

<ul>
    {% for book in books %}  #遍历列表
        <li>{{ book.name }}</li>
    {% endfor %}
</ul>
<ul>
    {% for book in books reversed%}  #反向遍历列表
        <li>{{ book.name }}</li>
    {% endfor %}
</ul>


{% for key,value in person.items %}  #遍历字典
    <p>key:{{ key }}</p>
    <p>value:{{ value }}</p>
{% endfor %}

<table border="1" cellspacing="0">
    <thead>
        <tr>
            <td>序号</td>
            <td>书名</td>
            <td>作者</td>
            <td>价格</td>
        </tr>
    </thead>
    <tbody>
        {% for book in books %}
            {% if forloop.first %}  #第一次遍历
                <tr style="background: antiquewhite">
            {% elif forloop.last %}  #最后一次遍历
                <tr style="background: aquamarine">
            {% else %}
                <tr style="background: blueviolet;">
            {% endif %}
                <td>{{ forloop.revcounter0 }}</td>  #下标从0开始
                <td>{{ book.name }}</td>
                <td>{{ book.author }}</td>
                <td>{{ book.price }}</td>
            </tr>
        {% endfor %}
    </tbody>
</table>

    for...in...empty标签:和for...in一样,只不过没有内容的时候执行empty中的内容;列入评论中如果没有评论则显示没有评论,有的话就显示评论内容

def index(request):
    context={
        "comments":[
            # "好文章"   #这个没有被注释的时候页面显示这里的内容,注释后显示empty下面的内容
        ]
    }

    return render(request,"index.html",context=context)
<ul>
    {% for comment in comments %}
        <li>{{ comment }}</li>
    {% empty %}
        <li>目前没有评论</li>
    {% endfor %}

</ul>

    with标签:在模板中定义一个变量,在访问视图中的变量有时候比较复杂,那么我们可以先把这个变量保存在另一个比较简单的变量中,以后通过这个简单的变量来访问。

    

context={
        "comments":[
            "好文章1",
            "好文章2",
            "好文章3",
            "好文章3",
        ]
    }

    return render(request,"index.html",context=context)
{{ comments.0 }}   
{{ comments.1 }}
{{ comments.2 }}<br>  #通过一般的变量访问方式
{% with comments.1 as a  %}  #使用with方式 
    {{ a }}
{% endwith %}

{% with a=comments.2  %}  #使用with方式 注意=两边不能有空格
    {{ a }}
{% endwith %}

    url标签:

from django.http import HttpResponse
from django.template.loader import render_to_string
from django.shortcuts import redirect,reverse,render

def index(request):
    return render(request,"index.html")

def book(request):
    return HttpResponse("图书")

def book_list(request,book_id,category):
    return HttpResponse("图书列表")

def login(request):
    next = request.GET.get("next")
    if next:
        return HttpResponse("已经登入")
    else:
        return HttpResponse("未登入")
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ul>
    <li><a href="/">首页</a></li>
    <li><a href="{% url 'front:book' %}">图书</a></li>   
    <li><a href="{% url 'front:book_list' book_id=1 category=2 %}">图书列表</a></li>   #关键字参数之间都是空格隔开
    <li><a href="{% url 'front:login' %}?next=hu">登入</a></li> #查询字符串参数直接在后面手动填写
</ul>

</body>
</html>

    autoescape标签:开启或者关闭这个标签内元素的自动转义功能

def index(request):
    context={
        "info":"<a href='http:www.baidu.com'>百度</a>"
    }
    return render(request,"index.html",context=context)
{% autoescape off %}   off是关闭,on是打开
    {{ info }}
{% endautoescape %}

    verbatim标签:不会去解析templates模板的语法

{% verbatim %}
    {{ hello }}
{% endverbatim %}     #页面直接显示的是 {{hello}}

 

4常用的过滤器: 在模板中有时候需要对数据进行一些处理才能使用;这个时候需要用到过滤器   ( | )

    View.py 和HTML代码如下:

content={
        "value1":"22",
        "value2":"asdfsdfa",
        "birthday":datetime.now(),
        "default":"",
        "default1":None,
        "first":["a","b","c"],
        "last":["a","b","c"],
        "join":["a","b","c"],
        "length":["a","b","c"],
        "random":["a","b","c"],
        "slice":["a","b","c"],
        "truncatechars":"我爱你,我的中国",
        "truncatechars_html":"<p>我爱你,我的中国</p>",
    }
    return render(request,"front_index.html",context=content)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>fornt_index</title>
</head>
<body>
    <h1>我是front下的首页</h1>
    <p>add:{{ value1 | add:"22" }}</p>
    <p>cut:{{ value2 | cut:"a" }}</p>
    <p>date:{{ birthday | date:"Y/m/d" }}</p>
    <p>default:{{ default | default:'没有东西' }}</p>
    <p>default_if_none:{{ default1 |default:"这个是none" }}</p>
    <p>first:{{ first | first }}</p>
    <p>last:{{ last |last }}</p>
    <p>join:{{ join |join:"/" }}</p>
    <p>lenght:{{ length|length }}</p>
    <p>random:{{ random |random }}</p>
    <p>slice:{{ slice |slice:"2:" }}</p>
    <p>truncatechars:{{ truncatechars | truncatechars:5 }}</p>
    <p>truncatechars_html:{{ truncatechars_html |truncatechars_html:5 }}</p>
</body>
</html>

 

    

 

5自定义过滤器:过滤器实际上就是一个python函数

  (1)先在这个APP下创建一个文件夹名为templatetags(必须),在这个包下创建我们过滤器文件(my_filter.py),里面写过滤器函数:(过滤器实际上就是一个函数,被注册到了模板中,最多只能有两个参数)(2)HTML中使用过滤器时需要先load这个过滤器{%load  my_filter%)(过滤器的文件名)

from django import template
register = template.Library()  #创建模板库对象

def greet(value,word):   #过滤器函数
    return value + word

register.filter("myfilter",greet)  #注册到模板库中,第一个参数过滤器的名字,第二个参数函数名字

___________________________________________________________
@register.filter(myfilter) #参数是过滤器的名字可以不传递;不传递的时候名字默认为函数名
def greet(value,word):
  return value+word

 

   有时候我们经常在朋友圈或者微博中看到一条信息显示的不是具体时间而是,刚刚,2分钟前,几天前之类的,以下就是这样一个过滤器:

from datetime import datetime
from django import template
register = template.Library()

@register.filter(name="my_time")
def time_since(value):
    if isinstance(value,datetime):
        now = datetime.now()
        timestamp = (now - value).total_seconds()
        if timestamp < 60:
            return "刚刚"
        elif timestamp>=60 and timestamp<60*60:
            minutes = int(timestamp/60)
            return "%s分钟前" %minutes
        elif timestamp>=60*60 and timestamp<60*60*24:
            hours = int(timestamp / (60*60))
            return "%s小时前"%hours
        elif timestamp>=60*60 and timestamp<60*60*24*30:
            day = int(timestamp/60/60/24)
            return "%s天前"%day
        else:
            return value.strftime("%Y/%m/%d %H:%M")
    else:
        return value

  View中和HTML中:

content={

"my_filter":datetime(year=2019,month=1,day=2,hour=12,minute=33,second=22)
}
return render(request,"front_index.html",context=content)

------------------------------------------------------------------------------------------------------------------------
{% load my_filter %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>fornt_index</title> </head> <body> <p>my_filter:{{ my_filter | my_time}}</p> </body> </html>

 

6模板的引入:

  被引入的为子模板,子模板可以使用父模板的变量

  {%include  " header.html" with username="xiaoming"%}   #可以带参数  with 变量名=变量值

7模板的继承

   父:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <header>
        <ul>
            <li><a href="">首页</a></li>
            <li><a href="">图书</a></li>
            <li><a href="">电影</a></li>
        </ul>
    </header>
    <div id="content">    
        {% block content %}   #从这里开个口子,子模板的内容可以从这里开始写
        我是父模板的内容      #父模板中的内容
        {% endblock %}
    </div>
    <footer>
        我是尾部
    </footer>
</body>
</html>

 

{% extends "base.html" %}  #必须放到第一行

{% block content %}   #从父模板开的口子,
    {{block.super}}  #如果父模板中的内容需要使用{{block.super}}
    我是index    #子模板自己定义的内容
{% endblock %}

8静态文件的加载

 步骤1: setting中的INSTALLED_APPS的'django.contrib.staticfiles',是开启的(默认开启)

步骤2:setting中设置了STATIC_URL = '/static/' (默认是有的)

步骤3:在每个APP中添加文件夹static(必须这个名字),文件夹下再建立一个文件夹和APP名字相同(一般这样设置防止多个APP的时候有相同名字的静态文件,防止混乱)(如:cms/static/cms/images/a.jpg)

步骤4:模板中先加载{%load static%},然后在设置静态文件的加载比如:<img src="{% static 'cms/images/a.jpg'%}">

以上4步就可以完成一个静态文件的加载。

公共的静态文件:我们可以放到项目下面的static文件夹中:项目下面建立文件夹static;然后在setting中设置STATICFILES_DIRS=[os.path.join(BASE_DIR "static")]

如果不想每次在模板中设置{%load static%},则需要在setting→TEMPLATES→OPTIONS中添加一个"builtins":["django.templatetags.static"],这样以后在使用static的时候不用每次都加载:

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',
            ],
            "builtins":["django.templatetags.static"]
        },
    },
]

特例:如果setting中没有设置:django.contrib.staticfiles;那么使用url映射的时候可以在这样设置:

from django.urls import path
from . import views
from django.conf.urls.static import static
from django.conf import settings
app_name = "front"
urlpatterns=[
    path("",views.index,name="index"),
]+static(settings.STATIC_URL,document_root = settings.STATIC_ROOT)