63-django-CBV刨析、模板層之模板語法傳值、過濾器、標籤、自定義過濾器、標籤、inclusion_tag、模板繼承、模板導入

今日內容概要

  • CBV源碼剖析
  • 模版層
    • 模版語法傳值
    • 模版語法之過濾器
    • 模版語法之標籤
    • 自定義過濾器、標籤及inclusion_tag
    • 模版的繼承
    • 模版的導入

FBV與CBV

"""
視圖函數便可以是函數也能夠是類
"""
# FBV
def index(request):
  return HttpResponse('OK')

# CBV
from django.views import View

"""只要是處理業務邏輯的視圖函數 形參裏面確定要有request"""
class MyClass(View):
  def get(self,request):
    return HttpResponse('get請求')
 	
  def post(self,request):
    return HttpResponse('post請求')
  
# 注意 CBV路由匹配寫法跟FBV有點不同(可是其實本質是同樣的)
url(r'^login/$',views.MyClass.as_view())

# 疑問:CBV可以作到根據不一樣的請求方式自動匹配對應的方法並執行???(******)

 

CBV源碼剖析

# 你本身不要修改源碼 除了bug很難找

# 突破口在urls.py
url(r'^login/',views.MyLogin.as_view())
# url(r'^login/',views.view)  FBV如出一轍
# CBV與FBV在路由匹配上本質是同樣的 都是路由 對應 函數內存地址
"""
函數名/方法名 加括號執行優先級最高
猜想
    as_view()
        要麼是被@staicmethod修飾的靜態方法
        要麼是被@classmethod修飾的類方法  正確
        
    @classonlymethod
    def as_view(cls, **initkwargs):
        pass
"""

    @classonlymethod
    def as_view(cls, **initkwargs):
        """
        cls就是咱們本身寫的類   MyCBV
        Main entry point for a request-response process.
        """
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)  # cls是咱們本身寫的類
            # self = MyLogin(**initkwargs)  產生一個咱們本身寫的類的對象
            return self.dispatch(request, *args, **kwargs)
            """
            之後大家會常常須要看源碼 可是在看python源碼的時候 必定要時刻提醒本身面向對象屬性方法查找順序
                先從對象本身找
                再去產生對象的類裏面找
                以後再去父類找
                ...
            總結:看源碼只要看到了self點一個東西 必定要問你本身當前這個self究竟是誰
            """
        return view
      
		# CBV的精髓
    def dispatch(self, request, *args, **kwargs):
        # 獲取當前請求的小寫格式 而後比對當前請求方式是否合法
        # get請求爲例
        # post請求
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            """
            反射:經過字符串來操做對象的屬性或者方法
                handler = getattr(本身寫的類產生的對象,'get',當找不到get屬性或者方法的時候就會用第三個參數)
         ###### getattr 就等同於 self.reques.method.lower() handler = 咱們本身寫的類裏面的get方法 """ else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) """ 自動調用get方法 """ # 要求掌握到不看源碼也可以描述出CBV的內部執行流程(******)

模版層

模版語法傳值

{{  }}:變量相關css

{%  %}:邏輯相關 html

def index(request):
    # 模版語法能夠傳遞的後端python數據類型
    n = 123
    f = 11.11
    s = '我也想奔現'
    b = True
    l = ['小紅','姍姍','花花','茹茹']
    t = (111,222,333,444)
    d = {'username':'jason','age':18,'info':'這我的有點意思'}
    se = {'晶晶','洋洋','嚶嚶'}

    def func():
        print('我被執行了')
        return '你的另外一半在等你'

    class MyClass(object):
        def get_self(self):
            return 'self'

        @staticmethod
        def get_func():
            return 'func'

        @classmethod
        def get_class(cls):
            return 'cls'
        
        # 對象被展現到html頁面上 就相似於執行了打印操做也會觸發__str__方法
        def __str__(self):
            return '到底會不會?'  
        
    obj = MyClass()

    # return render(request,'index.html',{})  # 一個個傳
    return render(request,'index.html',locals())


<p>{{ n }}</p>
<p>{{ f }}</p>
<p>{{ s }}</p>
<p>{{ b }}</p>
<p>{{ l }}</p>
<p>{{ d }}</p>
<p>{{ t }}</p>
<p>{{ se }}</p>
<p>傳遞函數名會自動加括號調用 可是模版語法不支持給函數傳額外的參數:{{ func }}</p>
<p>傳類名的時候也會自動加括號調用(實例化){{ MyClass }}</p>
<p>內部可以自動判斷出當前的變量名是否能夠加括號調用 若是能夠就會自動執行  針對的是函數名和類名</p>
<p>{{ obj }}</p>
<p>{{ obj.get_self }}</p>
<p>{{ obj.get_func }}</p>
<p>{{ obj.get_class }}</p>


# django模版語法的取值 是固定的格式 只能採用「句點符」 .
<p>{{ d.username }}</p>
<p>{{ l.0 }}</p>
<p>{{ d.hobby.3.info }}</p>
# 便可以點鍵也能夠點索引 還能夠二者混用

過濾器(過濾器只能最多有兩個參數)

# 過濾器就相似因而模版語法內置的 內置方法
# django內置有60多個過濾器 咱們不須要學這麼多 瞭解10個左右就差很少了 後面碰到了再去記憶
def index(request):
        n = 123
	f = 11.11
	s = '我也想奔現'
	b = True
	l = ['小紅', '姍姍', '花花', '茹茹']
	t = (111, 222, 333, 444)
	d = {'username': 'jason', 'age': 18, 'info': '這我的有點意思'}
	se = {'晶晶', '洋洋', '嚶嚶'}
	file_size = 1230214
	import datetime
	current_time = datetime.datetime.now()
	info = '啊是 的撒 打算 蔣 經 國迪斯科浪費口水都快的'
	egl = 'my name is egon i am very handsom'
	obj = MyClass()
	hhh = '<h1>唐嫣</h1>'
	sss = '<script>alert(123)</script>'
	from django.utils.safestring import mark_safe
	res = mark_safe('<h1>林允兒</h1>')


####### 基本語法
     {{數據|過濾器:參數}}

###### 轉義
# 前端
    {{ 數據|safe }}
# 後端
from django.utils.safestring import mark_safe
  res = mark_safe('<h1>新新</h1>')
"""
之後你在全棧項目的時候 前端代碼不必定非要在前端頁面書寫
也能夠如今先在後端寫好 而後傳遞給前端頁面
"""


<h1>過濾器</h1>
<p>統計長度:{{ s|length }}</p>
<p>默認值(第一個參數布爾值是True就展現第一個參數的值否在展現冒號後面的值):{{ b|default:'啥也不是' }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>日期格式化:{{ current_time|date:'Y-m-d H:i:s' }}</p>
<p>切片操做(支持步長):{{ l|slice:'0:4:2' }}</p>
<p>切取字符(包含三個點):{{ info|truncatechars:9 }}</p>
<p>切取單詞(不包含三個點 按照空格切):{{ egl|truncatewords:9 }}</p>
<p>切取單詞(不包含三個點 按照空格切):{{ info|truncatewords:9 }}</p>
<p>移除特定的字符:{{ msg|cut:' ' }}</p>
<p>拼接操做:{{ l|join:'$' }}</p>
<p>拼接操做(加法):{{ n|add:10 }}</p>
<p>拼接操做(加法):{{ s|add:msg }}</p>
<p>轉義:{{ hhh|safe }}</p>
<p>轉義:{{ sss|safe }}</p>
<p>轉義:{{ res }}</p>

標籤

標籤其實就是一堆邏輯,好比for循環,if判斷等前端

# for循環
{% for foo in l %}
    <p>{{ forloop }}</p>
    <p>{{ foo }}</p>  一個個元素
	{% endfor %}
{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 6, 'revcounter0': 5, 'first': True, 'last': False}

# if判斷
{% if b %}
    <p>baby</p>
{% elif s%}
    <p>都來把</p>
{% else %}
    <p>老baby</p>
{% endif %}


# for與if混合使用
{% for foo in lll %}
    {% if forloop.first %}
        <p>這是個人第一次</p>
    {% elif forloop.last %}
        <p>這是最後一次啊</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
    {% empty %}
        <p>for循環的可迭代對象內部沒有元素 根本無法循環</p>
{% endfor %}



# 處理字典其餘方法
{% for foo in d.keys %}
    <p>{{ foo }}</p>
{% endfor %}
{% for foo in d.values %} <p>{{ foo }}</p> {% endfor %}
{% for foo in d.items %} <p>{{ foo }}</p> {% endfor %} # with 起別名(名字太長一直輸太麻煩,起個簡短的別名方便操做) {% with d.hobby.3.info as nb %} <p>{{ nb }}</p> 在with語法內就能夠經過as後面的別名快速的使用到前面很是複雜獲取數據的方式 <p>{{ d.hobby.3.info }}</p> {% endwith %} 

自定義過濾器、標籤、inclusion_tag


這三個的使用前提,三步走
1.在應用下建立一個名字」必須「叫templatetags文件夾 2.在該文件夾內建立「任意」名稱的py文件 eg:mytag.py 3.在該py文件內"必須"先書寫下面兩句話(單詞一個都不能錯) from django import template register = template.Library()
from django import template

register = template.Library()

# 自定義過濾器(參數最多倆個) @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 'jason' 123 'egon' 123 %}</p> # 自定義inclusion_tag """ 內部原理 先定義一個方法 在頁面上調用該方法 而且能夠傳值 該方法會生成一些數據而後傳遞給一個html頁面 以後將渲染好的結果放到調用的位置 """ @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

{% load mytag %} {% left 5 %} # 總結:當html頁面某一個地方的頁面須要傳參數纔可以動態的渲染出來,而且在多個頁面上都須要使用到該局部 那麼就考慮將該局部頁面作成inclusion_tag形式 (在bbs的時候會使用到) 

模版的繼承

"""
大家有沒有見過一些網站
	這些網站頁面總體都大差不差 只是某一些局部在作變化	
"""
# 模版的繼承 你本身先選好一個你要想繼承的模版頁面
{% extends 'home.html' %}

# 繼承了以後子頁面跟模版頁面長的是如出一轍的 你須要在模版頁面上提早劃定能夠被修改的區域
{% block content %}
	模版內容
{% endblock %}

# 子頁面就能夠聲明想要修改哪塊劃定了的區域
{% block content %}
	子頁面內容	
{% endblock %}


# 通常狀況下模版頁面上應該至少有三塊能夠被修改的區域
	1.css區域
  2.html區域
  3.js區域
  {% block css %}

	{% endblock %}
  
  {% block content %}

	{% endblock %}
  
  {% block js %}

	{% endblock %}
  # 每個子頁面就均可以有本身獨有的css代碼 html代碼 js代碼
  
"""
通常狀況下 模版的頁面上劃定的區域越多 那麼該模版的擴展性就越高
可是若是太多 那還不如本身直接寫
"""

home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>圖書館管理系統</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
{% block css %}
    
{% endblock %}
<body>
<nav class="navbar navbar-inverse">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-3">
            <div class="list-group">
              <a href="/home/" class="list-group-item active">
                首頁
              </a>
              <a href="/login/" class="list-group-item">登陸</a>
              <a href="/register/" class="list-group-item">註冊</a>
            </div>
        </div>
        <div class="col-md-9">
            <div class="panel panel-primary">
              <div class="panel-heading">
                <h3 class="panel-title">Panel title</h3>
              </div>
              <div class="panel-body">
                  {% block aaa %}
                      <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 %}
              </div>
            </div>
        </div>
    </div>
</div>
{% block js %}

{% endblock %}
</body>
</html>  

login.html

{% extends 'home.html' %}


{% block css %}
    <style>
        h1  {
            color: red;
        }
    </style>
{% endblock %}


{% block aaa %}
    <h1 class="text-center">登錄頁面</h1>
        <form action="">
            <p>username: <input type="text" name="username" class="form-control"></p>
            <p>password: <input type="password" name="password" class="form-control"></p>
            <input type="submit" class="btn btn-primary btn-block">
        </form>
{% endblock %}


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

register.html

{% extends 'home.html' %}


{% block css %}
    <style>
        h1  {
            color: greenyellow;
        }
    </style>
{% endblock %}


{% block aaa %}
    <h1 class="text-center">註冊頁面</h1>
        <form action="">
            <p>username: <input type="text" name="username" class="form-control"></p>
            <p>password: <input type="password" name="password" class="form-control"></p>
            <input type="submit" class="btn btn-success btn-block">
        </form>
{% endblock %}


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

  

模版的導入

"""
將頁面的某一個局部當成模塊的形式
哪一個地方須要就能夠直接導入使用便可
"""
{% include 'wasai.html' %}

今日考題

1.什麼是FBV與CBV,能不能試着解釋一下CBV的運做原理
2.模版語法的傳值須要注意什麼,常見過濾器及標籤有哪些
3.自定義過濾器,標籤,inclusion_tag的流程
4.什麼是模版的繼承與導入,如何正確使用

 

今日重點回顧

CBV源碼

# 可以根據請求方式的不一樣自動匹配觸發對應的方法的執行(只要是視圖函數都應該有一個形參request)

# url			FBV與CBV在路由匹配上本質是同樣的都是路由對應函數內存地址
url(r'^index/',views.index)
url(r'^login/',views.MyClass.as_view())
# url(r'^login/',views.view)

# 源碼
MyClass.as_view()

@classonlymethod
def as_view(cls,**initkwargs):
  def view(*args,**kwargs):
    self = cls(*args,**kwargs)
    ...
    return self.dispatch(*args,**kwargs)
  	"""
  	你在後面看python源碼的時候 只要看到self點東西 
  	你必定要問你本身一些當前這個self究竟是誰???
  		屬性方法查找順序
  			對象自己找
  			產生對象的類中
  			類的父類們
  	"""
  return view

def dispatch(*args,**kwargs):
  if request.method.lower() in ['get','post',...]:
    	handler = getattr(self,request.method.lower(),'報錯信息')
  else:
    	handler = '報錯提示方法'
  return handler(request,*args,**kwargs)

  

模版語法的傳值

變量相關:{{}}python

邏輯相關:{%%}jquery

# 你要知道render支持兩種給html文件傳值的方式

# python全部的基本數據類型 函數名 類名 對象均可以被傳到html上
# 針對函數名和類名 模版語法會自動加括號調用(可是不支持傳遞額外的參數)

# 模版語法如何獲取容器類型裏面的數據  統一採用句點符 .
.key
.index
.key.index.index.key

 過濾器 

# 語法結構  最多隻能有兩個參數 
{{ data|過濾器:'參數'}}

|length
|default
|filesizeformat
|date:'Y-m-d'
|slice:'0:6:2'
|truncatechars(包含三個點)
|truncatewords(不包含三個點 按空格切)
|add
|cut
|join
|safe

轉義
	# 前端
  	|safe
  # 後端
  	from django.utils.safestring import mark_safe
    res = mark_safe('<h1>baby</h1>')
"""
前端代碼不必定非要在html頁面上書寫,也能夠在後端生成而後傳遞給html頁面!!!
"""

  

標籤

# for循環
{% for i in l %}
	{{ forloop }}
  {% empty %}
  		可迭代對象裏面沒有元素 無法for循環的時候自動走empty
{% endfor %}
	counter
	counter0
	first
	last

# if判斷
{% if user %}
	
{% elif age %}
	
{% else %}

{% endif %}

# with起別名
{% with data.0.name.1.password.2.heiheihei as t%}
	{{ t }}
{%endwith%}

# 模版語法也支持對字典獲取鍵 值 鍵值對操做
.keys
.values
.items

 

自定義過濾器、標籤、inclusion_tag 

"""
1.在對應的應用下建立一個名字必須叫templatetags文件夾
2.該文件夾內建立一個任意名稱的py文件	mytag.py
3.在該py文件內須要先書寫兩句固定的代碼
	from django import template
	register = template.Library()
"""
# 自定義過濾器
@register.filter(name='過濾器的名字')
def index(v1,v2):
  return v1 + v2

# 自定義標籤
@register.simple_tag(name='標籤的名字')
def func(*args):
  pass

# 自定義inclusion_tag
@register.inclusion_tag('html文件名')
def bar(n):
  return locals()  # 傳數據方式1
	return {}	# 傳數據方式2

# 如何使用上述三者
{% load mytag %}
{{ data|過濾器的名字:'參數' }}
{% 標籤的名字 參數1 參數2 參數3 參數4%}
{% bar %}

 

模版的繼承

"""
同一個html頁面 想重複的使用大部分樣式 只是局部修改
"""
# 繼承
{% extends '模版頁面名' %}

# 局部修改
	# 1.你須要先去模版頁面中劃定能夠被修改的區域
  	{% block '名字' %}
    	模版內容(666)
    {% endblock %}
  # 2.子頁面中即成了模版頁面以後 就能夠根據名字修改
  	{% block '名字' %}
    	子版內容
      
      子版頁面吃了能夠本身寫本身的以外 還能夠繼續使用模版的內容
      {{ block.super }}  666
      {{ block.super }}  666
      {{ block.super }}  666
      {{ block.super }}  666
    {% endblock %}
# 規律:通常狀況下模版頁面內至少應該有三塊區域
	css
  html
  js
  全部的子頁面中 均可以有本身獨立的css html 和js

# 利用模版的繼承 可以讓你的頁面更加的好維護

  

模版的導入

  {% include '模版文件名' %}ajax

做業

"""
必作題
1.整理今日內容,用本身的話術和思路整理到我的博客中
2.閱讀CBV源碼,截圖加註釋到手機一份,要求作到脫稿說出流程
3.利用模版的繼承及CBV完成網站首頁 登錄 註冊頁面搭建 實現三者相互交互
選作題
1.嘗試着作一作圖書管理系統(將所學的知識點所有用進去)
無名有名+反向解析+模版的繼承
"""
相關文章
相關標籤/搜索