1. 程式人生 > >python程式設計:從入門到實踐學習筆記-Django入門(四)

python程式設計:從入門到實踐學習筆記-Django入門(四)

建立其他網頁

我們接下來擴充“學習筆記”專案,建立兩個顯示資料的網頁,其中一個列出所有的主題,另一個顯示特定主題的所有條目。

模板繼承
編寫一個包含通用元素的父模板,並讓每個網頁都繼承這個模板,而不必在每個網頁中重複定義這些通用元素。這樣我們可以專注於開發每個網頁的獨特部分。
1.父模板
建立名為base.html的模板,和index.html放在同一個目錄,這個檔案包含所有頁面都有的元素——頂端的標題。

<p>
  <a href="{% url 'learning_logs:index' %}">Learning Log</a>
</p>

{% block content %}{% endblock content %}

在第二行中使用了一個模板標籤,模板標籤使用大括號和百分號({% %})表示,其是一小段生成網頁中顯示資訊的程式碼。
模板標籤{% url 'learning_logs:index' %}生成一個URL,該URL與learning_logs/urls.py中定義的名為index的URL模式匹配。在這個示例中,learning_logs是一個名稱空間,而index是該名稱空間中的一個名稱獨特的URL模式。
在結尾中插入了一對塊標籤,這個塊名為content,是一個佔位符,其包含的資訊將由子模板指定。
2.子模板
重新修改index.html

{% extends "learning_logs/base.html" %}

{% block content %}
  <p>Learning Log helps you keep track of your learning, for any topic you're learning about.</p>
{% endblock content %}

子模板第一行{% extends %}表示繼承了指定的父模板。這行程式碼會匯入base.html的所有內容,讓index.html的內容能夠新增在父模板預留的content塊中。
第二行,我們插入了content的{% content %}標籤,以定義content塊。不是從父模板繼承的內容都包含在裡邊。
最後一行,{% endblock content %}表示定義結束。

顯示所有主題的頁面
1.URL模式

#learning_logs/urls.py
from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^topics/$', views.topics, name='topics'),
]

新新增的正則表示式表示匹配的URL為:基礎URL後面跟著topics。接著匹配成功的話將請求都交給views.py中的函式topics()進行處理。
2.檢視
函式topics()需要從資料庫獲取資料,傳送給模板。

from django.shortcuts import render
from .models import Topic

def index(request):
    return render(request, 'learning_logs/index.html')

def topics(request):
    topics = Topic.objects.order_by('date_added')
    context = {'topics': topics}    
    return render(request, 'learning_logs/topics.html', context)

首先匯入與所需資料相關聯的模型。接著函式topics()包含一個形參:從伺服器收到的request物件。
函式的第二行表示查詢資料庫,請求Topic物件,並按屬性date_added對資料進行排序。最後把返回的查詢集春處在topics變數中。
函式的第三行定義了一個發給模板的上下文:是一個字典,其中的鍵是模板中用來訪問資料的名稱,值是傳送給模板的資料。
函式返回的時候,即建立使用資料的網頁時,我們把物件request和模板路徑,還有變數context傳遞給render()
3.模板
建立一個檔案 topics.html 和 index.html 同一資料夾。

{% extends "learning_logs/base.html" %}

{% block content %}

  <p>Topics</p>

  <ul>
    {% for topic in topics %}
       <li>{{ topic }}</li>
    {% empty %}  
       <li>No topics have been added yet.</li>
    {% endfor %} 
  </ul>

{% endblock content %}

首先繼承父模板,接著定義content塊。接著使用for迴圈的模板標籤遍歷字典context的列表topics。在模板中,不能使用縮排來表示迴圈結束,應當使用標籤{% endfor %}來指出迴圈的結束。雙花括號({{ topic }})裡的模板變數都會被替換為topic的當前值。
迴圈中間的模板標籤{% empty %}告訴django在列表topics為空時該怎麼辦:這裡是列印一條訊息,告訴使用者No topics have been added yet.
最後修改父模板,使其包含顯示所有主題的頁面連線:

<p>
  <a href="{% url 'learning_logs:index' %}">Learning Log</a> - 
  <a href="{% url 'learning_logs:topics' %}">Topics</a>
</p>

{% block content %}{% endblock content %}

執行本地伺服器可以看到

成功了!

顯示特定主題的網頁
1.URL模式

#learning_logs/urls.py
from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^topics/$', views.topics, name='topics'),
    url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
]

顯示特定主題的頁面的URL模式與前面的不同,因為其將使用主題的id屬性來指出請求的是哪個主題。

  • r'^topics/(?P<topic_id>\d+)/$'中的第二部分/(?P<topic_id>\d+)/表示與包含在兩個斜槓內的整數匹配,並將這個整數儲存在實參topic_id中。這部分表示式兩邊的括號捕獲URL中的值;?P<topic_id>將匹配的值儲存到topic_id中;\d+與包含在兩個斜槓內的任何數字都匹配,不管其多少位。

這個模式匹配成功時,將會呼叫檢視函式topic(),並把topic_id的值作為實參傳遞進去。
2.檢視

from django.shortcuts import render
from .models import Topic

def index(request):
    return render(request, 'learning_logs/index.html')

def topics(request):
    topics = Topic.objects.order_by('date_added')
    context = {'topics': topics}    
    return render(request, 'learning_logs/topics.html', context)

def topic(request, topic_id):
    topic = Topic.objects.get(id=topic_id)
    entries = topic.entry_set.order_by('-date_added')
    context = {'topic': topic, 'entries': entries}
    return render(request, 'learning_logs/topic.html', context)

函式get()獲取指定的主題。data_added前面的減號指定按降序排列,即先顯示最近的條目。
3.模板
建立一個檔案 topic.html 和 index.html 同一資料夾。

{% extends 'learning_logs/base.html' %}

{% block content %}

  <p>Topic: {{ topic }}</p>

  <p>Entries:</p>
  <ul>
  {% for entry in entries %}
    <li>
      <p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
      <p>{{ entry.text|linebreaks }}</p>
    </li>
  {% empty %}  
    <li>
      There are no entries for this topic yet. 
    </li>
  {% endfor %} 
  </ul>

{% endblock content %}

因為我們變數topic包含在字典context中,所以我們可以使用他。
每個專案列表項都將列出兩項資訊:條目的時間戳和完整的文字。列出時間戳date_added的值,我們可以在模板中使用豎線(|)表示模板過濾器——對模板變數的值進行修改的函式。
過濾器date:'M d, Y H:i'表示以這樣的格式顯示時間戳:January 1, 2015 23:00
過濾器linebreaks表示自動換行。
4.將顯示所有主題的頁面中的每個主題都設定為連結
修改topics.html

{% extends "learning_logs/base.html" %}

{% block content %}

  <p>Topics</p>

  <ul>
    {% for topic in topics %}
      <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a> <!-- here -->
    {% empty %}
      <li>No topics have been added yet.</li>
    {% endfor %}
  </ul>

{% endblock content %}

執行本地伺服器可以看到