1. 程式人生 > 其它 >第六篇:Django之模板層

第六篇:Django之模板層

第六篇:Django之模板層

目錄

一、模板語法傳值

模板語法簡單來說,只有兩種兩種格式。

# 第一種
{{  }}:變數相關
# 第二種
{%  %}:邏輯相關

模板語法可以傳遞後端的python資料型別給html頁面。

下面我們進行一一測試python的資料型別是否可以通過模板語法傳遞。

我們在後端設定這樣的資料,用來進行測試。

# 模板語法
def index(request):
    # 我們先定義python中的資料型別
    num = 111
    flo = 222.2
    bo = True
    li = ['楊毅', '雷超', '安安', '楊鑫', '權康', '港川']
    tup = ('小紅', '小花', '小蘭', '小紫', '小綠')
    dic = {'username': '楊毅', 'age': 18, 'gender': '男'}
    se = {'張無忌', '趙敏', '周芷若'}

    def func():
        return ('俺被執行了')

    class MyClass(object):
        def get_self(self):
            return '繫結方法'

        @staticmethod
        def get_func():
            return '靜態方法'

        @classmethod
        def get_class(cls):
            return '類方法'

        # 物件被展示到html頁面上 就類似於執行了列印操作也會觸發__str__方法
        def __str__(self):
            return '到底會不會執行呢?'

    obj = MyClass()
    return render(request, 'index.html', locals())

我們的index.html頁面中如此書寫。

<p>整形:{{ num }}</p>
<p>浮點型:{{ flo }}</p>
<p>布林值:{{ bo }}</p>
<p>列表:{{ li }}</p>
<p>元組:{{ tup }}</p>
<p>字典:{{ dic }}</p>
<p>集合:{{ se }}</p>
<p>函式:{{ func }}</p>
<p>類:{{ MyClass }}</p>
<p>物件:{{ obj }}</p>
<p>物件呼叫繫結方法:{{ obj.get_self }}</p>
<p>物件呼叫類方法:{{ obj.get_class }}</p>
<p>物件呼叫靜態方法:{{ obj.get_func }}</p>

之後我們便可以在瀏覽器中渲染出這樣的結果。

注意:

1、傳遞函式名會自動加括號呼叫,但是模版語法不支援給函式傳額外的引數。【顯示的是函式的返回值】
2、傳類名的時候也會自動加括號呼叫(例項化)
3、模板語法內部能夠自動判斷出當前的變數名是否可以加括號呼叫,如果可以就會自動執行。【針對的是函式名和類名】

Django模板語法取值的取值

django模版語法的取值,是固定的格式,只能採用“句點符” 。【也可以點索引,真是天才呀,哈哈。】

<p>{{ d.username }}</p>
<p>{{ l.0 }}</p>  
<p>{{ d.hobby.3.info }}</p>   # 即可以點鍵也可以點索引 還可以兩者混用

"""與jinja2模板語法不同"""
# jinja2模板語法和python語法極為類似。
"""  
jinja2模板語法
{{ user }}
{{ user.get('username')}}
{{ user.age }}  
{{ user['hobby'] }}
"""

二、模版語法之過濾器

過濾器就類似於是模版語法內建的內建方法,django內建有60多個過濾器,在這裡,我們只需要瞭解10多個就足矣。日後碰見在進行記憶。

基本語法:

{{資料|過濾器:引數}}

使用方式:

"""我們views.py中這樣設定"""
# 模板語法
def index(request):
    msg = 'my name is yang and my age is 18'
    is_true = False
    file_size = 123465798
    current_time = datetime.datetime.now()
    li = ['新垣結衣', '石原里美', '迪麗熱巴', '佟麗婭']
    info = '任時光匆匆離去,我只在乎你,心甘情願感受你的呼吸。'
    num = 100
    s = 'hello, '
    h5 = '<h1>迪麗熱巴</h1>'
    js = '<script>alert("迪麗熱巴")</script>'
    from django.utils.safestring import mark_safe
    res = mark_safe('<h1>新垣結衣</h1>')

    return render(request, 'index.html', locals())


"""index.html中進行測試"""
# 內部就是len(msg)
<p>統計長度:{{ msg|length }}</p>  # 統計長度:32

# 第一個引數布林值是True就展示第一個引數的值,否則展示冒號後面的值
<p>預設值:{{ is_true|default:'啥也不是' }}</p>  # 預設值:啥也不是

# 檔案大小【可以自動進行格式轉化】
<p>檔案大小:{{ file_size|filesizeformat }}</p>  # 檔案大小:117.7 MB

# 日期格式化
<p>日期格式化:{{ current_time|date:'Y-m-d H:i:s' }}</p>  # 日期格式化:2021-06-28 16:46:38

# 切片操作(支援步長)
<p>切片操作(支援步長):{{ li|slice:'0:4:2' }}</p>  # 切片操作(支援步長):['新垣結衣', '迪麗熱巴']

# 切取字元(包含三個點) 
<p>切取字元(包含三個點):{{ info|truncatechars:9 }}</p>  # 切取字元(包含三個點):任時光匆匆離...

# 切取單詞(不包含三個點 按照空格切)
<p>切取單詞(不包含三個點 按照空格切):{{ msg|truncatewords:4 }}</p>  # 切取單詞(不包含三個點 按照空格切):my name is yang ...

# 移除特定的字元
<p>移除特定的字元:{{ msg|cut:' ' }}</p>  # 移除特定的字元:mynameisyangandmyageis18
    
# 拼接操作
<p>拼接操作:{{ li|join:'$' }}</p>  # 拼接操作:新垣結衣$石原里美$迪麗熱巴$佟麗婭
 
# 拼接操作(加法)
<p>拼接操作(加法):{{ num|add:10 }}</p>  # 拼接操作(加法):110
<p>拼接操作(加法):{{ s|add:msg }}</p> # 拼接操作(加法):hello, my name is yang and my age is 18

# 轉義
"""前端"""
<p>轉義(html):{{ h5|safe }}</p>  # safe表示告訴瀏覽器是安全的,可以轉義
<p>轉義(js):{{ js|safe }}</p>  # js程式碼會先執行
"""後端"""
from django.utils.safestring import mark_safe
res = mark_safe('<h1>新垣結衣</h1>')
"""前端接收"""
<p>後端直接傳過來轉義資料:{{ res }}</p>

index.html中輸出的效果如下。

三、模版語法之標籤

  • for迴圈

    我們在index.html中這樣進行書寫。

{% for foo in li %}
    <p>{{ forloop }}</p>
{% endfor %}

我們發現在瀏覽器中的到這樣的資料【我們可以使用這些引數進行一定的操作】。

之後,我們可以這樣進行for迴圈。

{% for foo in li %}
    <p>{{ foo }}</p>
{% endfor %}
  • if判斷
{% if a %}
    ...
{% elif b %}
    ...
{% else %}
    ...
{% endif %}
  • for和if混合使用
{% for foo in li %}
    {% if forloop.first %}
        <p>這是第一次</p>
    {% elif forloop.last %}
        <p>這是最後一次</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
{% endfor %}

"""{% empty %} 如果for迴圈的可迭代物件內部沒有元素,則執行"""
{% for foo in list1 %}  # list1 = []
    {% if forloop.first %}
        <p>這是第一次</p>
    {% elif forloop.last %}
        <p>這是最後一次</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
    {% empty %}
        <p>for迴圈的可迭代物件內部沒有元素,根本沒法迴圈</p>
{% endfor %}

效果顯示如下。

  • 處理字典
# d.keys 模板語法函式自動執行
{% for foo in d.keys %}
    <p>{{ foo }}</p>
{% endfor %}

# d.values
{% for foo in d.values %}
    <p>{{ foo }}</p>
{% endfor %}

# d.items
{% for foo in d.items %}
    <p>{{ foo }}</p>
{% endfor %}
  • with起別名

    在with語法內就可以通過as後面的別名快速的使用到前面非常複雜獲取資料的方式。

{% with li.2 as beauty %}  # 通過索引取值
    <p>{{ beauty }}</p>
    <p>{{ li.2 }}</p>
{% endwith %}

效果如下。

四、自定義過濾器、標籤及inclusion_tag

"""
先三步走
	1.在應用下建立一個名字”必須“叫templatetags資料夾
	2.在該資料夾內建立“任意”名稱的py檔案 eg:mytag.py
	3.在該py檔案內"必須"先書寫下面兩句話(單詞一個都不能錯)
		from django import template
		
		register = template.Library()
"""
  • 自定義過濾器
"""mytag.py"""
# 自定義過濾器(引數最多兩個)【如果需要多個引數,可以'111 222'字元,不能是列表】
@register.filter(name='baby')
def my_sum(v1, v2):
    return v1 + v2

# 使用
{% load mytag %}  # 載入頁面
<p>{{ n|baby:666 }}</p>
  • 自定義標籤
# 自定義標籤(引數可以有多個)【類似於自定義函式】			
@register.simple_tag(name='plus')
def index(a,b,c,d):
    return '%s-%s-%s-%s'%(a,b,c,d)
# 使用
標籤多個引數彼此之間空格隔開
<p>{% plus 'yangyi' 123 123 123 %}</p>
  • 自定義inclusion_tag
"""
內部原理
	1、先定義一個方法 
	2、在頁面上呼叫該方法,並且可以傳值
	3、該方法會生成一些資料然後傳遞給一個html頁面
	4、之後將渲染好的結果放到呼叫的位置
"""

"""mytag.py"""
@register.inclusion_tag('left_menu.html')
def left(n):
    data = ['第{}項'.format(i) for i in range(n)]
    # 第一種
    # return {'data':data}  # 將data傳遞給left_menu.html
    # 第二種
    return locals()  # 將data傳遞給left_menu.html

"""left_menu.html"""
<ul>
    {% for foo in data %}
        <li>{{ foo }}</li>
    {% endfor %}
</ul>

"""使用"""
{% left 5 %}

# 總結:當html頁面某一個地方的頁面需要傳引數才能夠動態的渲染出來,並且在多個頁面上都需要使用到該區域性,那麼就考慮將該區域性頁面做成inclusion_tag形式。

五、模版的繼承

我們可以在瀏覽一些網站的時候觀察到,有些網站的整體都是大差不差的,只有一些區域性在進行變化。【當然,不使用模板的繼承也沒有問題,只不過程式碼過於冗餘】

我們先簡單建立頁面,樣式如下。訪問地址為127.0.0.1:8000/home/

我們可以在127.0.0.1:8000/reg127.0.0.1:8000/login的html頁面中,簡單的繼承home.html頁面,方式如下。

"""reg.html"""
{% extends 'home.html' %}

"""login.html"""
{% extends 'home.html' %}

如此一來,我們會發現訪問reg和login的頁面和home一樣。

如何進行操作呢?我們可以使用block將要修改的區域進行重新命名。。

 {% block content %}  # 將這塊區域重新命名為 content
     <div class="jumbotron">
          <h1>Hello, world!</h1>
           <p>...</p>
          <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
            </div>
{% endblock %}

那麼我們在reg.html和login.html中這樣進行操作即可。

"""reg.html"""
{% extends 'home.html' %}

{% block content %}
    <h1 class="text-center">使用者註冊</h1>
    <form action="" method="post">
        <p>username:<input type="text" class="form-control"></p>
        <p>password:<input type="password" class="form-control"></p>
        <input type="submit" class="btn btn-success btn-block" value="註冊">
    </form>
{% endblock %}


"""login.html"""
{% extends 'home.html' %}

{% block content %}
    <h1 class="text-center">使用者登入</h1>
    <form action="" method="post">
        <p>username:<input type="text" class="form-control"></p>
        <p>password:<input type="password" class="form-control"></p>
        <input type="submit" class="btn btn-danger btn-block" value="登入">
    </form>
{% endblock %}

即可實現實現下面效果。

同時,一般情況下模版頁面上應該至少有三塊可以被修改的區域,包括html區域、css區域和js區域。【每一個子頁面就都可以有自己獨有的css程式碼 html程式碼 js程式碼】,所以我們可以進行優化。

在要被繼承的html檔案中,事先劃分好要被繼承的區域。

"""home.html"""
{% block css %}
{% endblock %}
  
{% block content %}
{% endblock %}
  
{% block js %}
{% endblock %}
"""reg.html"""
{% extends 'home.html' %}

{% block css %}
    <style>
        body {
            background-color: wheat;
        }
    </style>
{% endblock %}

{% block content %}
    <h1 class="text-center">使用者註冊</h1>
    <form action="" method="post">
        <p>username:<input type="text" class="form-control"></p>
        <p>password:<input type="password" class="form-control"></p>
        <input type="submit" class="btn btn-success btn-block" value="註冊">
    </form>
{% endblock %}

{% block js %}
    <script>
        alert('註冊頁面')
    </script>
{% endblock %}
"""login.html"""
{% extends 'home.html' %}

{% block css %}
    <style>
        body {
            background-color: olivedrab;
        }
    </style>
{% endblock %}

{% block content %}
    <h1 class="text-center">使用者登入</h1>
    <form action="" method="post">
        <p>username:<input type="text" class="form-control"></p>
        <p>password:<input type="password" class="form-control"></p>
        <input type="submit" class="btn btn-danger btn-block" value="登入">
    </form>
{% endblock %}

{% block js %}
    <script>
        alert('登入頁面')
    </script>
{% endblock %}

由此可以實現下述效果。

補充:一般情況下,模版的頁面上劃定的區域越多,那麼該模版的擴充套件性就越高
但是如果太多,那還不如自己直接重寫。

六、模版的匯入

可以將html檔案當作一個模組,將區域性html程式碼寫入其中,需要的時候直接匯入即可使用。

"""新建一個new.html資料夾,其中存放"""
<h1>這是一個form表單</h1>

# 匯入方式
{% include 'wasai.html' %}