Django 模版語法與使用

Django 模版語法與使用

[TOC]css

django模板語言介紹 (摘自官方文檔) 連接

"""
Django模板語言
Django的模板語言旨在在功能和易用性之間取得平衡。它讓那些習慣使用HTML的人感到舒服。
若是您對其餘基於文本的模板語言(如Smarty 或Jinja2)有過接觸,那麼您應該對Django的模板感到賓至如歸。

哲學
若是您有編程背景,或者習慣於將編程代碼直接混合到HTML中的語言,那麼您須要記住,
Django模板系統不只僅是嵌入到HTML中的Python。這是一種設計,模板系統用於表達,而不是程序邏輯。

Django模板系統提供的標籤功能相似於一些編程結構 如 if,布爾,for標籤,循環標籤等 - 但這些標籤不是簡單地做爲相應的Python代碼執行,
模板系統不會執行任意Python表達式。默認狀況下,僅支持下面列出的標記,過濾器和語法(您能夠根據須要將本身的擴展添加到模板語言中)。

哲學
爲何使用基於文本的模板而不是基於XML的模板(如Zope的TAL)?咱們但願Django的模板語言不只可用於XML / HTML模板。
在World Online,咱們將其用於電子郵件,JavaScript和CSV。您能夠將模板語言用於任何基於文本的格式。

哦,還有一件事:讓人類編輯XML是虐待狂!
"""

什麼是模板?

模板只是一個文本文件。它能夠生成任何基於文本的格式(HTML,XML,CSV等)。
模板包含變量,這些變量在評估模板時將替換爲值,而變量則包含控制模板邏輯的標記。
只要是在html裏面有模板語法就不是html文件了,這樣的文件就叫作模板。

模板語句的 註釋

模板語句的註釋
{#{{ '10'|add_str:'5 '}}#}  
{#註釋內容#}

變量 {{ 變量 }}

  • 變量:語法爲 {{ }}:括號里加要渲染變量的變量值,變量名由字母數字和下劃線組成。
  • 代碼
#views 文件函數
def template_test(request):
    name = '鋼蛋'
    age = 18
    hobby = ['唱', '跳', 'rap', '籃球']
    lis = []
    st = ''
    dic = {
        'name': '鐵蛋',
        'age': 16,
        'hobby': hobby,
        'keys': 'xxxxx'
    }
    dic_2 = {}
    return render(request,'template_test.html',
 {'name':name_p,'age':age,'hobby':hobby,'lis':lis,'st':st,'dic':dic,'dic_2':dic_2})

# 模板文件html頁面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>郭楷豐</title>
</head>
<body>
{{ 啦啦啦啦啦 }}
<p>
    {{ name }}
</p>
<p>
   {{ age }}
</p>
<p>
    {{ hobby }}
</p>
<p>
    {{ lis }}
</p>
<p>
    {{ st }}
</p>
<p>
    {{ dic }}
</p>
<p>
    {{ dic_2 }}
</p>
</body>
</html>
  • 瀏覽器結果:

img

  • 小結: {{ }}裏填要渲染的變量,規範寫法,兩邊用括號隔開 如 {{ 變量 }}, 後端沒有傳參的頁面不顯示 img

img

點(.)在模板語言中有特殊的含義,用來獲取對象的相應屬性值。

  • 例子 代碼 .索引 .key .屬性 .方法
#views 文件函數
def template_test(request):
    lis = [1, 2, 3,4,5]
    dic = {"name": "黑蛋"}

    class Person(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age

        def dream(self):
            return " 我 is {} age {}歲...".format(self.name,self.age)

    gangdan = Person(name="鋼蛋", age=18)
    goudan = Person(name="狗蛋", age=17)
    tiedan  = Person(name="鐵蛋", age=16)

    person_list = [gangdan, goudan, tiedan]
    return render(request, "template_test.html", {"lis": lis, "dic": dic, "person_list": person_list})

# 模板文件html頁面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>郭楷豐</title>
</head>
<boby>
    <p>{{ lis.0 }}</p>   <!--取l中的第一個參數-->
    <p>{{ dic.name }}</p><!--取字典中key的值-->
    <p>{{ person_list.0.name }}</p><!--取對象的name屬性-->
    <p>{{ person_list.0.dream }}</p><!--.操做只能調用不帶參數的方法-->
</boby>
</html>
  • 小結:
#注:當模板系統遇到一個(.)時,會按照以下的順序去查詢:
1. 在字典中查詢
2. 屬性或者方法
3. 數字索引   # 索引不能爲負數

img

img

Tags 標籤 {% %} 表示邏輯相關的操做

  • 代碼例子
{% for foo in lis %}
<!--for循環-->
    {% if  %}
    <!--if判斷-->
    {% elif %}
    <!--elif判斷-->
    {% endif %}
    <!--if閉合符-->
    {% else %}
    <!--else判斷不成立執行-->
{% endfor %}
<!--for循環閉合符-->

<!--應用 模板html代碼-->
<form action="" method="post">
    <label for="inputEmail3" class="col-sm-2 control-label">書名: </label>
    <div class="col-sm-8">
        <input type="text" name="book_name" class="form-control" value="{{ edit_obj.title }}">
        <select name="pub_id" id="" class="btn btn-default  btn-sm">
            {% for foo in publishers %}
            {% if foo == edit_obj.pub %}
            <option selected value="{{ foo.pk }}"> {{ foo.name }}</option>
            {% else %}
            <option value="{{ foo.pk }}"> {{ foo.name }}</option>
            {% endif %}
            {% endfor %}
        </select>
    </div>
    <div class="text-center text-danger">{{ error }}</div>
    <div class="col-sm-offset-2 col-sm-10">
        <button type="submit" class="btn btn-default">提交</button>
    </div>
</form>

<!--應用 python邏輯代碼 #views 文件函數-->
def edit_book(request):
    error = ''
    pk = request.GET.get('pk')
    edit_obj = models.Book.objects.filter(id=pk)
    if not edit_obj:
        return HttpResponse('要編輯的數據不存在')
    if request.method == 'POST':
        book_name = request.POST.get('book_name')
        if not book_name.strip():
            error = "書名不能爲空"
        pub_id = request.POST.get('pub_id')
        if edit_obj[0].title == book_name and edit_obj[0].pub_id == int(pub_id):
            error = "未做修改"
        if not error:
            obj = edit_obj[0]
            obj.title = book_name
            obj.pub_id = int(pub_id)
            obj.save()
            return redirect('/book_list/')
    publishers = models.Publisher.objects.all()
    return render(request,'edit_book.html',{'edit_obj':edit_obj[0],'publishers':publishers,'error':error})
  • 執行效果

img

img

  • if語句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷。

  • js,python,模板語言的判斷邏輯html

    #python
    10>5>1  =》   10>5  and 5>1   true 
    
    #js
    10>5>1  =》   10>5  =》 true   =》   1>1  false
    
    #模板中  
    不支持連續連續判斷,也不支持算數運算(過濾器)
  • 注意事項

  • Django的模板語言不支持連續判斷,也不支持如下寫法:python

{% if a > b > c %}
...
{% endif %}
#不支持算數運算 + - * /
  • Django的模板語言中屬性的優先級大於方法
def xx(request):
    d = {"a": 1, "b": 2, "c": 3, "items": "100"}
    return render(request, "xx.html", {"data": d})
  • 如上,咱們在使用render方法渲染一個頁面的時候,傳的字典d有一個key是items而且還有默認的 d.items() 方法,此時在模板語言中:
{{ data.items }}   默認會取d的items key的值。

for循環可用的一些參數:

Variable Description
forloop.counter 當前循環的索引值(從1開始)
forloop.counter0 當前循環的索引值(從0開始)
forloop.revcounter 當前循環的倒序索引值(到1結束)
forloop.revcounter0 當前循環的倒序索引值(到0結束)
forloop.first 當前循環是否是第一次循環(布爾值)
forloop.last 當前循環是否是最後一次循環(布爾值)
forloop.parentloop 本層循環的外層循環
  • for ... empty

#for 標籤帶有一個可選的{% empty %} 從句,以便在給出的組是空的或者沒有被找到時,能夠有所操做。
{% for person in person_list %}
    <p>{{ person.name }}</p>
{% empty %}
    <p>sorry,no person here</p>
{% endfor %}

Filters 過濾器

  • 用來修改變量的顯示結果, 語法: {{ value|filter_name:參數 }} ':' 左右沒有空格沒有空格沒有空格web

  • 設置除法除盡 divisibleby:參數

img

with 的使用

  • 定義一箇中間變量(起個別名,只在with內部生效)
#寫法一
{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

#寫法二
{% with business.employees.count as total %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

img

default 系統默認值

{{ value|default:"nothing"}}
若是value值沒傳的話就顯示nothing
注:TEMPLATES的OPTIONS能夠增長一個選項:string_if_invalid:'找不到',能夠替代default的的做用。
(在配置文件settings.py設置)
  • 配置設置變量不傳參顯示值

img

  • 頁面效果

img

filesizeformat 文件大小人性化顯示

  • 將值格式化爲一個 「人類可讀的」 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)例如:
{{ value|filesizeformat }}
若是 value 是 123456789,輸出將會是 117.7 MB

add "加"

  • 給變量加參數,字符串默認嘗試轉int類型,轉不了就拼接
{{ value|add:"2" }}
value是數字4,則輸出結果爲6

{{ value|add:"hello" }}
value是數字666,則輸出結果爲666hello

{{ first|add:second }}
若是first是 [1,.2,3] ,second是 [4,5,6] ,那輸出結果是 [1,2,3,4,5,6]

lower 小寫

{{ value|lower }}

upper 大寫

{{ value|upper}}

title 標題

{{ value|title }}

ljust 左對齊

"{{ value|ljust:"10" }}"

rjust 右對齊

"{{ value|rjust:"10" }}"

center 居中

"{{ value|center:"15" }}"

length 長度

{{ value|length }}
返回value的長度,如 value=['a', 'b', 'c', 'd']的話,就顯示4.

slice 切片

{{value|slice:"2:-1"}}

first 取第一個元素

{{ value|first }}

last 取最後一個元素

{{ value|last }}

join 使用字符串拼接列表

  • 同python的str.join(list)
{{ value|join:" // " }}

cut 移除value中全部的與給出的變量相同的字符串

  • 若是value爲'i love you',那麼將輸出'iloveyou'.
{{ value|cut:' ' }}

truncatechars 按照字符截斷 ...也計數

  • 若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾
#參數:截斷的字符數
{{ value|truncatechars:9}}

truncatewords 按照單詞進行截斷, 只針對英文(...)不計數,中文按字計算

date 日期格式化

#後端
import datetime
def mul(request):
    value = datetime.datetime.now()
    return render(request, 'mul.html',{'value':value})

#模板語句
{{ value|date:"Y-m-d H:i:s"}}   #顯示格式 年-月-日 時:分:秒


#後端
import datetime
def mul(request):
    now = datetime.datetime.now()
    return render(request, 'mul.html',{'now':now})

#模板直接使用變量
{{ now }}  #顯示格式 June 19,2019,22:00 p.m.

#時間格式和默認值一塊兒使用
{{ obj.next_date|date:"Y-m-d"|default:"暫無" }}
  • 頁面效果

img

img

img

  • 可格式化輸出的字符: 點擊查看
  • 改配置文件設置顯示樣式 (一勞永逸的解決辦法)
#settings.py文件設置
USE_L10N = False  #更換爲False

DATETIME_FORMAT = 'Y-m-d H:i:s' #添加

#也能夠日期與時間分開設置  根據本身的需求設置
DATE_FORMAT = 'Y-m-d'   
TIME_FORMAT = 'H:i:s'

img

safe 防止xss攻擊 做用 取消轉義

  • 簡單瞭解xss攻擊
XSS攻擊全稱跨站腳本攻擊,是爲不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,
故將跨站腳本攻擊縮寫爲XSS,XSS是一種在web應用中的計算機安全漏洞,它容許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中。
    XSS是一種常常出如今web應用中的計算機安全漏洞,它容許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中。
好比這些代碼包括HTML代碼和客戶端腳本。攻擊者利用XSS漏洞旁路掉訪問控制——例如同源策略(same origin policy)。
這種類型的漏洞因爲被駭客用來編寫危害性更大的網絡釣魚(Phishing)攻擊而變得廣爲人知。對於跨站腳本攻擊,
駭客界共識是:跨站腳本攻擊是新型的「緩衝區溢出攻擊「,而JavaScript是新型的「ShellCode」。
  • xss攻擊流程

img

safe 主要做用

#Django的模板中會對HTML標籤和JS等語法標籤進行自動轉義,緣由顯而易見,這樣是爲了安全。
可是有的時候咱們可能不但願這些HTML元素被轉義,好比咱們作一個內容管理系統,後臺添加的文章中是通過修飾的,
這些修飾多是經過一個相似於FCKeditor編輯加註了HTML修飾符的文本,若是自動轉義的話顯示的就是保護HTML標籤的源文件。
爲了在Django中關閉HTML的自動轉義有兩種方式,若是是一個單獨的變量咱們能夠經過過濾器「|safe」的方式告訴Django這段代碼是安全的沒必要轉義。
  • 正常狀況下
#頁面代碼:
{% load my_tags %}
{{ 'https://www.baidu.com/'|show:'百度' }}

#自定過濾器代碼
@register.filter
def show(url,name):
    return "<a href = '{}'>{}</a>".format(url,name)
  • 頁面顯示效果

img

  • 過濾器函數 加is_safe = True 解除轉義
#自定過濾器代碼
@register.filter(is_safe = True)
def show(url,name):
    return "<a href = '{}'>{}</a>".format(url,name)
  • 頁面效果 img
  • 模板語句中加 safe 解除轉義
#模板語句
{% load my_tags %}
{{ 'https://www.baidu.com/'|show:'百度'|safe }}
  • 頁面效果 imgdjango

  • 也能夠導入模塊實現這種效果

img

img

自定義 filter

  • 當普通的內置過濾器,實現不了咱們的開發需求,那咱們能夠自定義過濾器來實現功能
自定義過濾器是隻能帶有一個或兩個參數的Python函數:
變量(輸入)的值 - -不必定是一個字符串
參數的值 - 這能夠有一個默認值,或徹底省略
例如,在過濾器{{var | foo:「bar」}}中,過濾器foo將傳遞變量var和參數「bar」。
自定義filter代碼文件擺放位置:
app01/
    __init__.py
    models.py
    templatetags/  # 在app01下面新建一個package package
        __init__.py
        app01_filters.py  # 建一個存放自定義filter的py文件
    views.py

自定義過濾器流程

  • 1 在app下建立一個名爲templatetags的python包
#注意 
在settings中的INSTALLED_APPS配置當前app,否則django沒法找到自定義的simple_tag

(模塊名只能是templatetags)
  • 2 在python中建立py文件,文件名能夠自定義 如:(my_tags.py)
  • 3 在py文件中寫:
from django import template

register = template.Library()  #固定寫法,不可改變
  • 4 寫函數+裝飾器
@register.filter  #過濾器
def add_str(value, arg):  # 最多有兩個
    return '{}-{}'.format(value, arg)
  • 5 寫頁面代碼 在使用自定義simple_tag和filter的html文件中導入以前建立的 my_tags.py
{% load my_tags %}   #先導入咱們自定義那個文件 my_tags
{{ name|add_str:age }}   #參數只能是兩個,一個參數是變量name ,一個是參數是後面的那個參數age
  • 執行結果

img

  • 自定義乘法過濾器 multioly

#過濾器函數
@register.filter
def multiply1(value,arg):
    return value * arg
    
#模板語句
{% load my_tags %}
<p>{{ 6|multiply1:'6' }}</p>
<p>{{ 6|multiply1:6 }}</p>
<p>{{ '10'|multiply1:5 }}</p>
  • 執行結果

img

img

  • 自定義除法過濾器 division

#過濾器函數
@register.filter
def division(value,arg):
    return value / arg

#模板語句
{% load my_tags %}
<p>{{ 6|division:6 }}</p>
<p>{{ 6|division:1 }}</p>
  • 執行結果

img

  • 自定義除法過濾器 add

#過濾器函數
@register.filter
def add(value,arg):
    return value + arg   #能夠這樣寫,可是轉換不了會報錯 int(value) + int(arg)

#模板語句
{% load my_tags %}
<p>{{ 6|add:6 }}</p>
<p>{{ 6|add:0 }}</p>

<p>{{ '鋼蛋g'|add:18 }}</p>
  • 執行結果

img

img

  • 自定義減法過濾器 subtraction

#過濾器函數
@register.filter
def add(value,arg):
    return value - arg

#模板語句
{% load my_tags %}
<p>{{ 6|add:6 }}</p>
<p>{{ 6|add:0 }}</p>
  • 執行結果

img

自定義標籤 simpletag

  • 與自定義過濾器區別,能夠接受更多參數,使用標籤引用{{% %}
與自定義filter相似(也是在python包的templatetags文件下,建立此標籤),只不過接收更靈活的參數。

#simple_tag  代碼
@register.simple_tag(name="plus")
def plus(a, b, c):
    return "{} + {} + {}".format(a, b, c)

#使用simple tag  自定義標籤 
{% load app01_demo %}
{# simple tag #}
{% plus "1" "2" "abc" %}
    
    
#例子  標籤代碼
@register.simple_tag
def join_str(*args, **kwargs):
    return '{} - {} '.format('*'.join(args), '$'.join(kwargs.values()))

# 模板
{% load my_tags %}
{% join_str '1' '2' '鋼蛋' k1='3' k2='4' %}
  • 執行效果

img

自定義標籤 inclusion_tag

  • 多用於返回html代碼片斷 (動態變量 分頁)

img

img

  • app文件下 建立python包

img

  • 包文件名必須爲 templatetags

img

  • 在templatetags裏面建立任意 .py 文件

img

  • 寫函數

img

  • html頁面代碼

    #分頁顯示代碼
    <nav aria-label="Page navigation">
      <ul class="pagination">
        <li>
          <a href="#" aria-label="Previous">
            <span aria-hidden="true">&laquo;</span>
          </a>
        </li>
        {% for i in num %}
            <li><a href="#">{{ i }}</a></li>
        {% endfor %}
        <li>
          <a href="#" aria-label="Next">
            <span aria-hidden="true">&raquo;</span>
          </a>
        </li>
      </ul>
    </nav>
    
    
    #頁面1
    {% load my_tags %}
    {% page 5 %}
    
    #頁面2
    {% load my_tags %}
    {% page 1 %}
  • 顯示效果

img

img

img

  • 總結:

自定義過濾器 filter 只能接受兩個參數 調用的時候使用 {{ filter }}

自定義標籤  simpletag  與自定義過濾器區別,能夠接受更多參數,使用標籤引用{{%  %}
                                            
自定義標籤 inclusion_tag  多用於返回html代碼片斷,使用標籤引用{{% %}

csrf_token 跨站請求僞造保護

在頁面的form表單裏面寫上{% csrf_token %}
  • 如圖

img

img

靜態文件相關

#做用 在配置文件找到靜態文件別名,與文件地址進行拼接,這樣別名改了,也不會影響,靜態文件的導入

{% load static %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />

#引用JS文件時使用:
{% load static %}
<script src="{% static "mytest.js" %}"></script>

#某個文件多處被用到能夠存爲一個變量
{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>


{% load static %}
 <link rel="stylesheet" href="{% static '/plugins/bootstrap-3.3.7/css/bootstrap.css' %}">
 <link rel="stylesheet" href="{% static '/css/dsb.css' %}">
{% static '/plugins/bootstrap-3.3.7/css/bootstrap.css' %}  

{% get_static_prefix %}   # 獲取別名
  • 獲取配置文件的 別名

img

img

母版和繼承

什麼是母版?

普通的HTML頁面 母版頁用於處理html頁面相同部份內容,避免出現冗餘代碼,減小重複html頁面的編寫,提升代碼複用性,方便代碼修改.

繼承寫法

#在子頁面中在頁面最上方使用下面的語法來繼承母板。
{% extends '母版文件名.html' %}

block 塊

經過在母板中使用{% block  xxx %}來定義"塊"。
在子頁面中經過定義母板中的block名來對應替換母板中相應的內容。

#定義block
{% block 塊名 %}
{% endblock  %} #還能夠{{% endblock 塊名 %}}來關閉標籤,更加清新

#使用block
{% block 塊名 %}

    #本身的內容   

{% endblock  %}

#母版內容和本身內容都使用
{% block 塊名 %}

    #本身的內容   
    {% block.super %}

{% endblock  %}

子頁面替換母版 block塊

img img

  • 注意事項
注意的點:

1. {% extends 'base.html' %} 寫在第一行   前面不要有內容 有內容會顯示
2. {% extends 'base.html' %}  'base.html' 加上引號   否則當作變量去查找
3. 把要顯示的內容寫在block塊中
4. 定義多個block塊,定義 css  js 塊

組件

#做用
能夠將經常使用的頁面內容如導航條,頁尾信息等組件保存在單獨的文件中,而後在須要使用的地方按以下語法導入便可。

#示列  單獨建一個html  page
<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
      </a>
    </li>
    {% for i in num %}
        <li><a href="#">{{ i }}</a></li>
    {% endfor %}
    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">&raquo;</span>
      </a>
    </li>
  </ul>
</nav>

#別的頁面 引用
{% include 'page.html' %}
相關文章
相關標籤/搜索