18.3 創(chuàng)建網(wǎng)頁: 學習筆記主頁
使用Django創(chuàng)建網(wǎng)頁的過程通常分為三個階段: 定義URL森篷、編寫視圖和編寫模板谈飒。
URL模式描述了URL是如何設(shè)計的艰额,讓Django知道如何將瀏覽器請求與網(wǎng)站URL匹配臂港,以確定返回哪個網(wǎng)頁卿捎。
每個URL都被映射到特定的視圖——視圖函數(shù)獲取并處理網(wǎng)頁所需的數(shù)據(jù)莱衩。視圖函數(shù)通常調(diào)用一個模板,后者生成瀏覽器能夠理解的網(wǎng)頁娇澎。
18.3.1 映射URL
用戶通過在瀏覽器中輸入URL以及單擊鏈接來請求網(wǎng)頁笨蚁,因此我們需要確定項目需要哪些URL。主頁URL最重要趟庄,它是用戶用來訪問項目的基礎(chǔ)URL括细。當前,基礎(chǔ)URL(http://localhost:8000/)返回默認Django網(wǎng)頁
修改文件夾learning_log中的文件urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include,url
urlpatterns = [
path('admin/', admin.site.urls),
url(r'', include('learning_logs.urls', namespace='learning_logs')),
]
這是一個針對整個項目的urls.py文件戚啥,變量urlpatterns 包含項目中的應用程序的URL奋单。添加一行代碼來包含模塊learning_logs.urls,這行代碼包含實參namespace, 可以讓我們將learning_logs的URL同項目中的其他URL區(qū)分開
創(chuàng)建learning_logs的urls.py文件
"""定義learning_logs的URL模式"""
from django.conf.urls import url
from . import views
app_name = 'learning_logs'
urlpatterns = [
url(r'^$', views.index, name='index'),
]
url的第二個實參指定了要調(diào)用的視圖函數(shù)猫十。請求的URL于前述正則表達式匹配時览濒,Django將調(diào)用views.index。第三個實參name='index' 將這個URL模式的名稱指定為index拖云,讓我們能夠在代碼的其他地方引用它贷笛。每當需要提供到這個主頁的鏈接時,我們都將使用這個名稱宙项,而不編寫URL
18.3.2 編寫視圖
from django.shortcuts import render
# Create your views here.
"""學習筆記的主頁"""
def index(request):
return render(request, 'learning_logs/index.html')
由于我們需要處理任何數(shù)據(jù)乏苦,因此這個函數(shù)只包含調(diào)用render()的代碼。這里向函數(shù)render()提供了兩個實參:原始請求對象以及一個可用于創(chuàng)建網(wǎng)頁的模板。
18.3.3 編寫模板
在learning_logs中新建文件夾templates汇荐,再創(chuàng)建名為learning_logs的文件夾洞就,新建一個index.html的文件
index.html 內(nèi)容
<p>Learning Log</p>
<p>Learning Log helps you keep track of your learning, for any topic you're
learning about.</p>
放置目錄
(ll_env) c5220056@GMPTIC:~/myworkplace/learning_logs/templates/learning_logs$ ls
index.html
再請求項目的基礎(chǔ)URL——http://localhost:8000/,將看到剛才創(chuàng)建的網(wǎng)頁掀淘,而不是默認的Django網(wǎng)頁旬蟋。
注: 創(chuàng)建網(wǎng)頁的過程看起來可能復雜,但將URL革娄、視圖和模板分離的效果實際上很好咖为。這讓我們能夠分別考慮項目的不同方面,且在項目很大時稠腊,讓各個參與者可專注于其最擅長的方面躁染。例如:數(shù)據(jù)庫專家可專注于模型,程序員可專注于視圖代碼架忌,而Web設(shè)計人員可專注于模板吞彤。
18.4 創(chuàng)建其他網(wǎng)頁
18.4.1 模板繼承
1. 父模板
創(chuàng)建一個名為base.html的模板,這個文件包含所有頁面都有的元素叹放;其他模板都繼承base.html
# base.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模式雹嗦。
{% block content %}{% endblock content %} 是一對塊標簽。這個塊名為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 %}
18.4.2 顯示所有主題的頁面
1. URL模式
首先聪全,我們定義顯示所有主題Topic的頁面的URL泊藕,我們將使用URL http://localhost:8000/topics/返回所有主題的頁面
修改learning_logs/urls.py
from django.conf.urls import url
from . import views
app_name = 'learning_logs'
urlpatterns = [
# index
url(r'^$', views.index, name='index'),
# show all topics
url(r'^topics/$', views.topics, name='topics'),
]
2. 視圖
函數(shù)topics()需要從數(shù)據(jù)庫中獲取一些數(shù)據(jù),并將其發(fā)送給模板难礼,我們需要在views.py中添加代碼如下:
from django.shortcuts import render
from .models import Topic
# Create your views here.
def index(request):
return render(request, 'learning_logs/index.html')
def topics(request):
"""show all topics"""
topics = Topic.objects.order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
這里content是我們定義的一個將要發(fā)送給模板的上下文娃圆。上下文是一個字典,其中的鍵是我們將在模板中用來訪問數(shù)據(jù)的名稱蛾茉, 而值是我們要發(fā)送給模板的數(shù)據(jù)讼呢。
3. 模板
顯示所有主題的頁面的模板接受字典context,以便能夠使用topics()提供的數(shù)據(jù)臀稚。
創(chuàng)建topics.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 %}
模板中使用的代碼與Python代碼存在一些重要差別:Python使用縮進來指出哪些代碼行是for循環(huán)的組成部分怪蔑,而在模板中形帮,每個for循環(huán)都必須使用{% endfor %}標簽來顯式地指出其結(jié)束為止玻粪。因此在模板中橄仍,循環(huán)類似于下面這樣:
{% for item in list %}
do something with each item
{% endfor %}
修改父模板,使其包含到顯式所有主題的頁面鏈接:
# base.html
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a>
<a href="{% url 'learning_logs:topics' %}">Topics</a>
</p>
{% block content %}{% endblock content %}
點擊topics稚机,將看到類似如下圖所示的網(wǎng)頁
18.4.3 顯示特定主題的頁面
接下來幕帆,我們想要創(chuàng)建一個專注于特定主題的頁面——顯示該主題的名稱及該主題的所有條目。同樣赖条,我們將定義一個新的URL 模式失乾,編寫一個視圖并創(chuàng)建一個模板。我們還將修改顯示所有主題的網(wǎng)頁纬乍,讓每個項目列表項都是一個連接碱茁,單擊它將顯示相應主題的所有條目。
1. URL模式
顯示特定主題的頁面的URL模式與前面的所有URL模式都稍有不同仿贬,因為它將使用主題的id 屬性來指出請求的是哪個主題纽竣。例如,如果用戶要查看主題Chess(其id 為1)的詳細頁面茧泪,URL將為http://localhost:8000/topics/1/蜓氨。下面是與這個URL匹配的模式,它包含在learning_logs/urls.py中:
# urls.py
from django.conf.urls import url
from . import views
app_name = 'learning_logs'
urlpatterns = [
# index
url(r'^$', views.index, name='index'),
# show all topics
url(r'^topics/$', views.topics, name='topics'),
# show detail info for specific topic
url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
]
2. 視圖
views.py
from django.shortcuts import render
from .models import Topic
# Create your views here.
def index(request):
return render(request, 'learning_logs/index.html')
def topics(request):
"""show all topics"""
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)
3. 模板
topic.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 %}
4. 將顯示所有主題的頁面中的每個主題都設(shè)置為鏈接
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
</li>
{% empty %}
<li>No topics have been added yet.</li>
{% endfor %}
</ul>
{% endblock content %}
我們使用模板標簽url根據(jù)learning_logs中名為topic的URL模式來生成合適的鏈接队伟。這個URL模式要求我們提供實參topic_id穴吹,因此我們在模板標簽url中添加了屬性topic.id。
如果你刷新顯示所有主題的頁面嗜侮,再單擊其中的一個主題港令,將看到類似于下圖的頁面: