Django web 框架學習之旅(2)

《Django Web框架》

目錄

Django的框架模式

  • MVC 設計模式

    • MVC 代表 Model-View-Controller(模型-視圖-控制器) 模式。

    • 作用: 降低模塊間的耦合度(解耦)

    • MVC

      • M 模型層(Model), 主要用於對數據庫層的封裝
      • V 視圖層(View), 用於向用戶展示結果
      • C 控制(Controller ,用於處理請求、獲取數據、返回結果(重要)
    • 如圖:

  • MTV 模式
    MTV 代表 Model-Template-View(模型-模板-視圖) 模式。這種模式用於應用程序的分層開發

    • 作用:
      • 降低模塊商的耦合度(解耦)
    • MTV
      • M – 模型層(Model) 負責與數據庫交互
      • T – 模板層(Template) 負責呈現內容到瀏覽器
      • V – 視圖層(View) 是核心,負責接收請求、獲取數據、返回結果
    • 如圖:

模板 Templates

  • 什麼是模板

    1. 模板是html頁面,可以根據視圖中傳遞的數據填充值相應的頁面元素。
    2. 模板層提供了一個對設計者友好的語法用於渲染向用戶呈現的信息。
  • 模板的配置

    • 創建模板文件夾<項目名>/templates
    • 在 settings.py 中有一個 TEMPLATES 變量
      1. BACKEND : 指定模板的引擎
      2. DIRS : 指定保存模板的目錄們
      3. APP_DIRS : 是否要在應用中搜索模板本
      4. OPTIONS : 有關模板的選項們
  • 默認的模塊文件夾templates

  • 修改settings.py文件,設置TEMPLATES的DIRS值爲'DIRS': [os.path.join(BASE_DIR, 'templates')],

# file: settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # 'DIRS': [],
        'DIRS': [os.path.join(BASE_DIR, 'templates')],  # 添加模板路徑
        'APP_DIRS': True,  # 是否索引各app裏的templates目錄
        ...
    },
]
  1. 模板的加載方式
    1. 通過 loader 獲取模板,通過HttpResponse進行響應
      from django.template import loader
      # 1.通過loader加載模板
      t = loader.get_template("模板名稱")
      # 2.將t轉換成字符串
      html = t.render()
      # 3.響應
      return HttpResponse(html)
      
      • 示例:
      from django.template import loader
      
      def render_page1(request):
          # 1.通過loader加載模板
          t = loader.get_template("page1.html")
          # 2.將t轉換成字符串
          html = t.render()
          # 3.響應
          return HttpResponse(html)
      
    2. 使用 render() 直接加載並響應模板
      • 示例:
      from django.shortcuts import render
      return render(request,'模板的名稱')
      
      • 示例
      def render_page2(request):
          from django.shortcuts import render
          return render(requese, 'page1.html')
      

Django 模板語言: (The Django template language)

模板的傳參
  • 模板傳參是指把數據形成字典,傳參給模板,由模板渲染來填充數據
  1. 使用 loader 加載模板
    t = loader.get_template('xxx.html')
    html = t.render(字典數據)
    return HttpResponse(html)
    
  2. 使用render加載模板
    return render(request,'xx.html',字典數據)
    
模板的變量
  1. 在模板中使用變量語法
    • {{ 變量名 }}
    1. 後端中必須將變量封裝到字典中才允許傳遞到模板上
      dic = {
          "變量1":"值1",
          "變量2":"值2",
      }
      
模板的標籤
  1. 作用

    • 將一些服務器端的功能嵌入到模板中
  2. 標籤語法

    {% 標籤 %}
    ...
    {% 結束標籤 %}
    
  3. if 標籤

    {% if 條件表達式 %}
    ...
    {% elif 條件表達式 %}
    ...
    {% else %}
    ...
    {% endif %}
    
  4. if 標籤裏的布爾運算符

    • if 條件表達式裏可以用的運算符 ==, !=, <, >, <=, >=, in, not in, is,is not, not、and、or
    • 在if標記中使用實際括號是無效的語法。 如果您需要它們指示優先級,則應使用嵌套的if標記。
  5. for 標籤

    1. 語法
      {% for 變量 in 可迭代對象 %}
      {% endfor %}
      
    2. 內置變量 - forloop
      變量 描述
      forloop.counter 循環的當前迭代(從1開始索引)
      forloop.counter0 循環的當前迭代(從0開始索引)
      forloop.revcounter 循環結束的迭代次數(從1開始索引)
      forloop.revcounter0 循環結束的迭代次數(從0開始索引)
      forloop.first 如果這是第一次通過循環,則爲真
      forloop.last 如果這是最後一次循環,則爲真
      forloop.parentloop 對於嵌套循環,這是圍繞當前循環的循環
  6. for … empty 標籤

    1. 語法
      {% for 變量 in 可迭代對象 %}
      {% empty %}
      {% endfor %}
      
  7. cycle 標籤

    • 循環從cycle 列表後的參數中進行取值,每次調用進行一次更換
    • 這個標籤經常用於循環中,如處理表格的隔行變色
    • 語法:
      {% for o in some_list %}
          <tr class="{% cycle 'row1' 'row2' %}">
              ...
          </tr>
      {% endfor %}
      
    • 示例:
      <table>
          <tr>
              <th>姓名</th>
              <th>年齡</th>
              <th>成績</th>
          </tr>
          <tr style="background:red;">
              <td>小張</td>
              <td>20</td>
              <td>100</td>
          </tr>
          <tr style="background:blue;">
              <td>小張</td>
              <td>20</td>
              <td>100</td>
          </tr>
          <tr style="background:red;">
              <td>小張</td>
              <td>20</td>
              <td>100</td>
          </tr>
          <tr style="background:blue;">
              <td>小張</td>
              <td>20</td>
              <td>100</td>
          </tr>
      <!-- 以下可以用cycle 標籤完成 -->
      {% for s in students %}
          <tr style="background: {% cycle 'red' 'yellow' %};">
              <td>{{ s.name }}</td>
              <td>{{ s.age }}</td>
              <td>{{ s.score }}</td>
          </tr>
      {% endfor %}
      </table>
      
  8. 註釋 和 comment標籤

  • {# 開頭, 以 #}結束範圍內的文字信息將會被模板的渲染系統忽略掉
  • 如:
    • {# <h1>此處的文字不會被生成html文檔</h1> #}
  1. comment 標籤
  • 在 {% comment %} 和 {% endcomment %},之間的內容會被忽略,
  • 作用: 用於註釋,可以用此來記錄代碼被註釋掉的原因。
  • 注: comment 標籤不能嵌套使用
  • 例如:
    <div>Rendered text with {{ pub_date|date:"c" }}</div>
    {% comment "Optional note" %}
        <div>Commented out text with {{ create_date|date:"c" }}</div>
    {% endcomment %}
    comment標籤不能嵌套使用。
    

過濾器

  1. 作用

    • 在變量輸出前對變量的值進行處理
    • 您可以通過使用 過濾器來改變變量的顯示。
  2. 語法

    • {{變量|過濾器1:參數值1|過濾器2:參數值2 …}}
  3. 有用的過濾器

    過濾器 說明
    default 如果value的計算結果爲False,則使用給定的默認值。 否則,使用該value。
    default_if_none 如果(且僅當)value爲None,則使用給定的默認值。 否則,使用該value。
    floatformat 當不使用參數時,將浮點數舍入到小數點後一位,但前提是要顯示小數部分。
    truncatechars 如果字符串字符多於指定的字符數量,那麼會被截斷。 截斷的字符串將以可翻譯的省略號序列(“…”)結尾。
    truncatewords 在一定數量的字後截斷字符串。
    lower 將字符串轉換爲全部小寫。
    upper 將字符串轉換爲大寫形式
  4. escape 示例:

    • escape 轉義字符串的HTML。 具體來說,它使這些替換:
    < 轉換爲 &lt;
    > 轉換爲 &gt;
    '(單引號)轉換爲 &#39;
    "(雙引號)轉換爲 &quot;
    & 轉換爲 &amp;
    
  5. 文檔參見:

模板的繼承

  • 模板繼承可以使父模板的內容重用,子模板直接繼承父模板的全部內容並可以覆蓋父模板中相應的塊

  • 定義父模板中的塊 block標籤

    • 標識出哪些在子模塊中是允許被修改的
    • block標籤:在父模板中定義,可以在子模板中覆蓋
    {% block block_name %}
    定義模板塊,此模板塊可以被子模板重新定義的同名塊覆蓋
    {% endblock block_name %}
    
  • 繼承模板 extends標籤(寫在模板文件的第一行)

    • 子模板繼承語法標籤
      • {% extends '父模板名稱' %}
      • 如:
        • {% extends 'base.html' %}
    • 子模板 重寫父模板中的內容塊
    {% block block_name %}
    子模板塊用來覆蓋父模板中 block_name 塊的內容
    {% endblock block_name %}
    
    • 重寫的覆蓋規則
      • 不重寫,將按照父模板的效果顯示
      • 重寫,則按照重寫效果顯示
    • 注意
      • 模板繼承時,服務器端的動態內容無法繼承
  • 參考文檔

  • 模板的繼承示例:

    # file : url.py
    from django.conf.urls import url
    from . import views
    urlpatterns = [
        ...
        url(r'^index', views.index),
        url(r'^goods_list1', views.goods_list),
        url(r'^goods_list2', views.goods_list2),
        url(r'^user_info1', views.user_info1),
        url(r'^user_info2', views.user_info2),
    ]
    # file: views.py
    def index(request):
        return render(request, 'index.html')
    
    def goods_list(request):
        return render(request, 'goods_list.html')
    
    def goods_list2(request):
        return render(request, 'goods_list2.html')
    
    def user_info1(request):
        return render(request, 'user_info_page1.html')
    
    def user_info2(request):
        return render(request, 'user_info_page2.html')
    
    • 基類模板
    <!-- file : base.html -->
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>{% block title %}{% endblock %}</title>
        <style>
            /* 基礎樣式設置 */
            body, h1, h2, h3, h4, h5, h6, p, ul, ol {
                margin: 0;
                padding: 0;
                border: 0;
                list-style: none;
            }
    
            /* 整體 */
            #container {
                width: 1000px;
                margin: 0 auto;
            }
    
            /* 頂部 */
            #top {
                width: 1000px;
                height: 100px;
                background: gray;
            }
    
            /* 主體 */
            #main {
                display: flex;
                justify-content: space-between;
            }
    
            {% block head_style %}
            {% endblock %}
    
            /* 底部 */
            #foot {
                width: 1000px;
                height: 100px;
                background: orange;
            }
        </style>
    </head>
    <body>
    <!-- 整體 -->
    <div id="container">
        <!-- 1.頂部 -->
        <div id="top">
            標題
        </div>
        <!-- 2.中間主體部分 -->
        <div id="main">
            {% block body_info %}
            {% endblock %}
        </div>
        <!-- 3.底部 -->
        <div id="foot">
            底部
        </div>
    </div>
    </body>
    </html>
    
    • 子類主頁模板
    {% extends "base.html" %}
    
    {% block title %}首頁{% endblock %}
    {% block head_style %}
    /* 主體左側 */
    #main #main_index {
        width: 1000px;
        height: 500px;
        background: pink;
    }
    {% endblock %}
    
    {% block body_info %}
    <!-- 2.1 主面中間的信息 -->
    <div id="main_index">
        主頁
    </div>
    {% endblock %}
    
    
    • 子類商品列表模板
    {% extends "base.html" %}
    
    {% block title %}商品列表{% endblock %}
    {% block head_style %}
        /* 主體左側 */
        #main #left-type{
            width:300px;
            height:500px;
            background:pink;
        }
        /* 主體右側 */
        #main #right-goods{
            width:700px;
            height:500px;
            background:blue;
        }
    {% endblock %}
    
    {% block body_info %}
    <!-- 2.1 主面中間的信息 -->
        <!-- 2.1主體左邊 -->
        <div id="left-type">
            <ul>
                <li>手機</li>
                <li>電腦</li>
                <li>戶車</li>
            </ul>
        </div>
    
        {% block goods_info %}
        <div id="right-goods">
            手機列表
        </div>
        {% endblock %}
    {% endblock %}
    
    {% extends "goods_list.html" %}
    
    {% block goods_info %}
    <div id="right-goods">
        電腦列表
    </div>
    {% endblock %}
    
    {# 此模板繼承自base.html #}
    {% extends "base.html" %}
    
    {% block title %}用戶信息{% endblock %}
    {% block head_style %}
        /* 主體左側 */
        #main #left-list{
            width:300px;
            height:500px;
            background:pink;
        }
        /* 主體右側 */
        #main #right-info{
            width:700px;
            height:500px;
            background:yellow;
        }
    {% endblock %}
    
    {% block body_info %}
    <!-- 2.1 主面中間的信息 -->
        <!-- 2.1主體左邊 -->
        <div id="left-list">
            <ul>
                <li>修改密碼</li>
                <li>修改頭像</li>
                <li>修改聯繫方式</li>
            </ul>
        </div>
    
        {% block user_detail %}
        <div id="right-info">
            <div>原密碼<input type="password"></div>
            <div>新密碼<input type="password"></div>
            <div>新密碼<input type="password"></div>
        </div>
        {% endblock %}
    {% endblock %}
    
    {# 此模板繼承自user_info_page1.html #}
    {% extends "user_info_page1.html" %}
    
    
    {% block user_detail %}
    <div id="right-info">
        <div>手機號<input type="text"></div>
        <div>家庭住址<input type="text"></div>
    </div>
    {% endblock %}
    

url 反向解析

  • url()的name關鍵字參數
    • 作用:
      • 根據url 列表中的name=關鍵字傳參給 url確定了個唯一確定的名字,在模板中,可以通過這個名字反向推斷出此url信息
    • 語法
      • url(regex, views, kwargs=None, name=“別名”)
      • ex:
        • url(r’^user_login/$’, views.login, name=“login”)
    • 通過別名實現地址的反向解析
      在模板中: {% url ‘some-url-name’ %}
      {% url ‘別名’ %}
      {% url ‘別名’ ‘參數值1’ ‘參數值2’ %}
    • 示例:
    # file: url.py
    from django.conf.urls import url
    from . import views
    urlpatterns = [
        ...
        url(r'^fav_list', views.fav_list, name="fav_list"),
        url(r'^fav_list/page/(\d+)', views.fav_list_page, name="fav_list_page"),
    
    ]
    # file: views.py
    def fav_list(request):
        return render(request, 'fav_list.html')
    
    def fav_list_page(request, page):
        return render(request, 'fav_list.html')
    
    <html>
    <head></head>
    <body>
        <div><a href="/fav_list">我的收藏</a></div>
        <div><a href="{% url "fav_list" %}">我的收藏</a></div>
    
        <a href="/fav_list/page/1">我的收藏第1頁</a>
        <a href="/fav_list/page/2">我的收藏第2頁</a>
        <a href="/fav_list/page/3">我的收藏第3頁</a>
        <a href="{% url 'fav_list_page' '200' %}">我的收藏第4頁</a>
    </body>
    </html>
    

靜態文件

  1. 什麼是靜態文件
    • 不能與服務器端做動態交互的文件都是靜態文件
    • 如:圖片,css,js,音頻,視頻,html文件(部分)
  2. 靜態文件配置
    • 在 settings.py 中配置一下兩項內容:
    1. 配置靜態文件的訪問路徑
      • 通過哪個url地址找靜態文件
      • STATIC_URL = ‘/static/’
      • 說明:
        • 指定訪問靜態文件時是需要通過 /static/xxx或 127.0.0.1:8000/static/xxx
        • xxx 表示具體的靜態資源位置
    2. 配置靜態文件的存儲路徑
      • 靜態文件在服務器端的保存位置
      • STATICFILES_DIRS=(os.path.join(BASE_DIR,‘static’),)
    3. 示例:
      # file: setting.py
      STATICFILES_DIRS = [
          os.path.join(BASE_DIR, "static")
      ]
      
  3. 訪問靜態文件
    1. 使用靜態文件的訪問路徑進行訪問

      • 訪問路徑: STATIC_URL=/static/
      • 示例:
        <img src="/static/images/lena.jpg">
        <img src="http://127.0.0.1:8000/static/images/lena.jpg">
        
    2. 通過 {% static %}標籤訪問靜態文件
      {% static %}表示的就是靜態文件訪問路徑

      1. 加載 static
        {% load static %}
      2. 使用靜態資源時
        語法:{% static ‘靜態資源路徑’ %}
        <img src="{% static ‘images/lena.jpg’ %}">
    • 示例:
      # file: url.py
      from . import views
      
      urlpatterns = [
          url(r'^admin/', admin.site.urls),
          url(r'^show_image', views.show_image)
      ]
      # file: views.py
      from django.shortcuts import render
      
      def show_image(request):
          return render(request, "show_image.html")
      
      <html>
      <head></head>
      <body>
      <h1>this is lena!</h1>
      <img src="/static/images/lena.jpg">
      <h1>this is templates lena!</h1>
      {% load static %}
      <img src="{% static 'images/lena.jpg' %}">
      </body>
      </html>
      

Django中的應用 - app

什麼是應用(app)

  • 應用在Django項目中是一個獨立的業務模塊,可以包含自己的路由,視圖,… …
  • Django中,主文件夾是不處理用戶具體請求的.主文件夾的作用是做項目的初始化以及請求的分發(分佈式請求處理).具體的請求是由應用來進行處理的

創建應用app

  • 創建應用的指令
    • python3 manage.py startapp 應用名稱
    • 如:
      • python3 manage.py startapp music

Django應用的結構組成

1. `migrations` 文件夾
    - 保存數據遷移的中間文件
2. `__init__.py`
    - 應用子包的初始化文件
3. `admin.py`
    - 應用的後臺管理配置文件
4. `apps.py`
    - 應用的屬性配置文件
5. `models.py`
    - 與數據庫相關的模型映射類文件
6. `tests.py`
    - 應用的單元測試文件
7. `views.py`
    - 定義視圖處理函數的文件
  • 配置安裝應用
    • 在 settings.py 中配置應用, 讓此應用能和整個項目融爲一體
      # file : settings.py 
      INSTALLED_APPS = [
          ... ...,
          '自定義應用名稱'
      ]
      
      
    • 如:
      INSTALLED_APPS = [
          # ....
          'user',  # 用戶信息模塊
          'music',  # 收藏模塊
      ]
      
  • 應用的分佈式路由
    • 使用include 函數讓某個正則匹配後關聯分支到某個app
    # file : <項目名>/urls.py
    from django.conf.urls import include
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^music/', include('music.urls')),
        url(r'^sport/',include('sport.urls')),
        url(r'^news/',include('news.urls')),
    ]
    # file : <App名>/urls.py
    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        # 購物車模塊用到的路由
        url(r'^page1', views.page1),
        url(r'^page2', views.page2),
        url(r'^page3', views.page3),
        # ...
    ]
    
    

end…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章