🍖Django框架之模板層

一.兩種模板方法

  • 變量相關 : {{ }}css

  • 邏輯相關 : {% %}html

二.註釋

  • 註釋是代碼之母 : {# #}

三.模板語法之傳值

1.Python中基本數據類型傳值

def test_func(request):
    s = "Hello 派大星!"
    i = 1314520
    f = 1.75
    l = [1,2,3,4,5]
    d = {"name":"shawn","age":23}
    t = (2,3,4,5,5)
    se = {3,4,5,'rr'}
    b = True
    
    # 傳值方式一 : 使用字典的格式一個個傳
    return render(request,'test.html',{'strs':s,'ints':i,'lists':l,...})
    # 傳值方式二 : 使用 locals()將當前名稱空間全部的變量名所有傳遞微頁面
    return render(request,'test.html',locals())
  • test.html 文件
<h1>{{ s }}</h1>
<h1>{{ i }}</h1>
<h1>{{ f }}</h1>
<h1>{{ l }}</h1>
<h1>{{ d }}</h1>
<h1>{{ t }}</h1>
<h1>{{ se }}</h1>
<h1>{{ b }}</h1>

image-20210318194630391

2.函數與類的傳遞

def test_func(request):

    def aa():
        print("aa--->")
        return 'I am aa'

    class Bar(object):

        def cc(self):
            print("Bar-->cc")

    B1 = Bar()
    return render(request, 'test.html', locals())
  • 模板層
<h1>{{ aa }}</h1>
<h1>{{ Bar }}</h1>
<h1>{{ B1 }}</h1>

image-20210318194502925

3.函數名與類名注意點

  • 傳遞函數名與類名都會自動加括號調用
  • 傳入函數名獲得的結果是函數的返回值
  • 模板語法不支持額外的傳參,也就是函數沒法傳參

4.傳值方式優缺點 :

  • 傳值方式一 : 傳值精確, 不會形成資源浪費
  • 傳值方式二 : 傳值簡單, 可能形成必定的資源浪費

四.模板語法之獲取值

  • django模板語法取值只能採用句點符(.),也就是點前端

  • 能夠根據索引以及鍵取值,支持多個不少個點........python

# views.py
def test_func(request):
    ll = [1,2,{"name":"shawn","age":23,"hobby":["read","study"]}]
    return render(request,"test.html",{"ll":ll})

# 想要取出愛好read
# test.html
<h1>{{ ll.2.hobby.0 }}</h1>

image-20210318195629158

五.模板語法之過濾器Filter

1.過濾器說明

  • 相似於Python的內置方法
  • 將豎槓左側的數據當作第一個參數傳給右邊的過濾器
  • 語法 : {{ [數據]|過濾器:可選參數 }}
  • 注意 : 豎槓左右兩邊沒有空格
  • 過濾器參數包含空格的話須要使用引號包裹
  • 過濾器最多隻能有兩個參數

2.經常使用過濾器使用

  • django中大約60中過濾器,下面只介紹經常使用過濾器
# views.py
def test_func(request):
    s = "Hello 派大星!"
    i = 1314520
    f = 1.75
    l = [1,2,3,4,5]
    d = {"name":"shawn","age":23}
    t = (2,3,4,5,5)
    se = {3,4,5,'rr'}
    b = True
    w = 'aa bb cc dd ee ff'

    return render(request,'test.html',locals())
<!-- test.html-->
<p>統計長度:{{ s|length }}</p>
<!-- add數字相加,字符拼接-->
<p>加法運算:{{ i|add:1000 }}</p>
<p>字符串拼接:{{ s|add:'Hello 海綿寶寶' }}</p>
<p>拼接:{{ s|join:'@' }}</p>
<p>切片:{{ l|slice:'0:5:2' }}</p>
<p>日期格式:{{ ctime|date:'Y年-m月-d日 H時:i分:s秒' }}</p>
<!-- 若是第一個參數的布爾值是true則顯示左邊的值,不然顯示default後的值-->
<p>默認值:{{ b|default:'哈哈' }}</p>  
<p>文件大小:{{ file_size|filesizeformat }}</p>
<!-- 截取內容包含三個點,而且算在字符個數以內-->>
<p>截取文本:{{ w|truncatechars:6 }}</p>
<!-- 截取內容包含三個點,但不算在單詞個數以內,單詞識別是以空格來區分的-->
<p>截取單詞:{{ w|truncatewords:3 }}</p>

image-20210326223226444

3.轉意

  • 後端使用轉意
from django.utils.safestring import mark_safe
html_safe = mark_safe('<h1>你好</h1>')
  • 前端使用轉意
{{ html|safe }}

六.模板語法之標籤

相似於Python中的流程控制django

1.for循環

{% for i in l %}
    <p>{{ forloop }}</p>
    <p>{{ i }}</p>  # 循環從列表 l 中取出一個個元素
{% endfor %}

咱們再看看 forloop 輸出的是什麼:後端

image-20210318214321276

2.if 判斷

# i = 90

{% if i > 100 %}
    <p>is True</p>
{% elif i > 80 %}
    <p>is two</p>
{% else %}
    <p>is no</p>
{% endif %}

image-20210318215255704

3.for 與 if 混合使用

{% for i in l %}
    {% if forloop.first %}
        <p>is first</p>
    {% elif forloop.last %}
        <p>is last</p>
    {% else %}
        <p>{{ i }}</p>
    {% endif %}
{% endfor %}

image-20210318215606748

4.empty : 空

{% for foo in request %}
    {% empty %}
        <p>傳入的數據爲空,沒法進行循環</p>
{% endfor %}

image-20210318215938511

5.with : 取別名

{% with ll.2.hobby.0 as hb %}
    <p>{{ hb }}</p>             # 可使用別名取值
    <p>{{ ll.2.hobby.0 }}</p>   # 也可使用原來的方式取值
{% endwith %}

image-20210318220320333

6.字典values、keys、items方法

{% for k in d.keys %}
    <p>{{ k }}</p>
{% endfor %}

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

{% for kv in d.items %}
    <p>{{ kv }}</p>
{% endfor %}

七.自定義過濾器、標籤、inclusion_tag

相似於Python中的自定義函數app

1.建立 templatetags 文件

  • 首先在應用下建立一個名字必須叫"templatetags"文件夾
  • 在改文件夾下建立一個任意名稱的 py 文件 (例 : mytag)
  • 在該 py 文件內固定書寫兩行代碼
from django import template
register = template.Library()

2.自定義過濾器

  • 自定義過濾器最多隻能有兩個形參
from .templatetags.mytag import register

# 在模板層導入自定義的過濾器時使用的是這裏指定的名字
@register.filter(name='myfilter')  
def sums(a, b):   # 函數名隨便起什麼
    return a + b  # 返回兩個參數的和
{% load mytag %}  # 導入tag文件
<p>{{ i|myfilter:100 }}</p>  # 使用myfilter過濾器

image-20210318225017009

3.自定義標籤

  • 自定義標籤能夠有多個參數
from .templatetags.mytag import register

# 在模板層導入自定義的標籤時使用的是這裏指定的名字
@register.simple_tag(name="my_tag")
def my_join(a,b,c,d):          # 函數名任意
    return f'{a}/{b}/{c}/{d}'  # 返回參數拼接後的結果
{% load mytag %}  # 導入tag文件
<p>{% my_tag 'hello' 'pai' 'da' 'xing' %}</p>  # 標籤以後的多個參數彼此之間用空格隔開

image-20210318230441986

  • 示例二
from .templatetags.mytag import register

# 在模板層導入自定義的標籤時使用的是這裏指定的名字
@register.simple_tag(name="my_tag")
def my_join(a,b):          # 函數名任意
    return a+b             # 返回和
{% load mytag %}
<p>{% my_tag i 100 %}</p>

image-20210318231336629

4.自定義 inclusion_tag

  • inclusion_tag 的內部原理:
  • 在HTML頁面中導入寫好的 inclusion_tag 並調用了
  • 觸發了py文件中一個函數的執行併產生結果
  • 產生的結果經過模板語法傳遞給一個HTML頁面進行渲染
  • 渲染完畢後又返回調用 inclusion_tag 的位置
  • 示例
from .templatetags.mytag import register

@register.inclusion_tag('test.html',name='my_incl_tag')  # 第一個參數是須要渲染的HTML頁面
def func(n):
    data=[]
    for i in range(n):
        data.append(f'第{i}頁')
    return locals()
# test.html 文件
{% load mytag %}
<p>{% my_incl_tag 6 %}</p>
# test2.html
{{ data }}
{% for foo in data %}
    {% if forloop.first %}
        <p>{{foo}}</p>
    {% elif forloop.last %}
        <p>{{ foo }}</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
{% endfor %}

test.html 頁面中調用了 inclusion_tag----->觸發執行了一個函數產生結果並渲染到 test2.html 頁面中, 渲染完又返回 test.html 頁面函數

image-20210318235133415

八.模板的導入

相似於後端的模塊, 想要什麼頁面,局部直接導入便可oop

{% include 'edit.html' %}  # 直接在當前HTML文件裏面顯示 edit.html 文件的內容

九.模板的繼承

1.模板繼承的使用

  • 模板的繼承首先須要選擇一個模板頁面, 在該頁面裏面使用 block 劃定能夠被更改的區域
# 母板頁面 'home.html' 文件
{% block [區域名稱] %}
......
{% endblock %}
  • 想要繼承的頁面可使用 extends 來繼承某一個頁面
# 子版
{% extends 'home.html' %}
{% block [區域名稱] %}
......
{% endblock %}

子版繼承了模板, 那麼子版的總體格式與模板同樣, 被 block 劃分了的區域能夠本身隨意更改post

2.模板的三個區域

  • 母板在劃分區域的時候通常有三個區域
{% block css %}
    # css區域
{% endblock %}

{% block content %}
    # HTML區域
{% endblock %}

{% block js %}
    # js區域
{% endblock %}

目的是爲了讓子版具備獨立的css、js等,增長擴展性

  • 子版也能夠繼續使用母版劃定了區域內的內容
{{ block.super }}

3.示例

  • 路由層
urlpatterns = [
    path('admin/', admin.site.urls),
    path('home/', views.func),
    path('index/', views.func2,name='index_name'),
]
  • 視圖層
def func(request):
    return render(request,'home.html')

def func2(request):
    return render(request,'index.html')
  • 模板層
# home.html
{% block left-body %}
<div class="jumbotron">
    <h1>Hello, world!</h1>
    <p>這裏是一個block劃分的區域</p>
    <p><a class="btn btn-primary btn-lg" href="{% url 'index_name' %}" role="button">Learn more</a></p>
</div>
{% endblock %}

# index.html
{% extends 'home.html' %}
{% block left-body %}
    <div class="row">
      <div class="col-xs-6 col-md-4 col-md-offset-2">
        <a href="#" class="thumbnail">
          <img src="../static/img/11.png" alt="...">
        </a>
      </div>
        <div class="col-xs-6 col-md-4 col-md-offset-2">
            <a href="#" class="thumbnail">
              <img src="../static/img/11.png" alt="...">
            </a>
        </div>
    </div>
{% endblock %}
  • home.html 頁面

image-20210319153623274

  • index.html 頁面

image-20210319153709598

十.小練習

1.需求

  • 增刪改查功能

  • 將對用戶增刪改查的功能使用模板的繼承來寫

  • 代碼除了模板層與以前無太大差異

2.代碼實現

  • urls.py 文件
from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('home/', views.home_func,name='home_name'),
    re_path('^edit/(\d+)', views.edit_func,name='edit_name'),
    re_path('^del/(\d+)', views.del_func,name='del_name'),
    path('insert/', views.insert_func,name='insert_name'),
]
  • views.py 文件
def home_func(request):
    user_obj_list = models.User.objects.all()
    return render(request,'home.html',locals())

def edit_func(request,id):
    if request.method == "POST":
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        age = request.POST.get('age')
        models.User.objects.filter(id=id).update(name=name,pwd=pwd,age=age)
        return redirect('home_name')
    user_obj = models.User.objects.filter(id=id).first()
    return render(request,'edit.html',{'user_obj':user_obj})

def del_func(request,id):
    models.User.objects.filter(id=id).delete()
    return redirect('home_name')

def insert_func(request):
    if request.method == "POST":
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        age = request.POST.get('age')
        models.User.objects.create(name=name,pwd=pwd,age=age)
        return redirect('home_name')
    return render(request,'insert.html')
  • 模板層文件
# home.html 文件

##[導航欄代碼]
##[左側邊欄代碼]
##[右邊內容由block劃分]
{% block left-body %}
    <div class="container">
        <div class="row">
            <h1 class="text-center">用戶數據</h1>
            <div class="col-md-8 col-md-offset-2">
                <table class="table table-hover table-striped">
                    <thead>
                    <tr>
                        <th>編號</th>
                        <th>姓名</th>
                        <th>密碼</th>
                        <th>年齡</th>
                        <th>操做</th>
                    </tr>
                    </thead>
                    <tbody>
                        {% for user_obj in user_obj_list %}
                            <tr>
                                <td>{{ user_obj.id }}</td>
                                <td>{{ user_obj.name }}</td>
                                <td>{{ user_obj.pwd }}</td>
                                <td>{{ user_obj.age }}</td>
                                <td>
                                    <a href="{% url 'del_name' user_obj.id %}">刪除</a>
                                    <a href="{% url 'edit_name' user_obj.id %}">修改</a>
                                </td>
                            </tr>
                        {% endfor %}
                    </tbody>
                </table>
            <div class="col-md-8 col-md-offset-2">
                <form action="{% url 'insert_name' %}" method="get">
                    <input type="submit" class="btn btn-block btn-warning" value="新增">
                </form>
            </div>
            </div>
        </div>
    </div>
{% endblock %}


# edit.html 文件

{% extends 'home.html' %}
{% block left-body %}
<div class="container">
<div class="row">
    <h2 class="text-center">修改數據</h2>
    <div class="col-md-8 col-md-offset-2">
        <form action="" method="post">
            username:
            <input type="text" name="name" class="form-control" value="{{ user_obj.name }}">
            password:
            <input type="text" name="pwd" class="form-control" value="{{ user_obj.pwd }}">
            age:
            <input type="number" name="age" class="form-control" value="{{ user_obj.age }}">
            <input type="submit" value="提交" class="btn btn-block btn-warning">
        </form>
    </div>
</div>
</div>
{% endblock %}


# insert.html 文件

{% extends 'home.html' %}
{% block left-body %}
    <div class="container">
    <div class="row">
        <h2 class="text-center">插入數據</h2>
        <div class="col-md-8 col-md-offset-2">
            <form action="" method="post">
            username:
                <input type="text" class="form-control" name="name">
            password:
                <input type="test" class="form-control" name="pwd">
            age:
                <input type="number" class="form-control" name="age">
                <input type="submit" value="提交" class="btn btn-block btn-warning">
            </form>
        </div>
    </div>
    </div>
{% endblock %}

image-20210319171604527

image-20210319171632069

image-20210319171716321

image-20210319171748532

相關文章
相關標籤/搜索