?
目錄
6. 鏈接到頁面new_topic
topics.html
19.1.2 添加新條目
1. 用于添加新條目的表單
forms.py
2. URL模式new_entry
urls.py
3. 視圖函數(shù)new_entry()
views.py
4. 模板new_entry
new_entry.html
5. 鏈接到頁面new_entry
topic.html
19.1.3 編輯條目
1. URL模式edit_entry
urls.py
2. 視圖函數(shù)edit_entry()
views.py
往期快速傳送門??(在文章最后):
感謝大家的支持!歡迎訂閱收藏!專欄將持續(xù)更新!
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Add a new topic:</p>
1 <form action="{% url 'learning_logs:new_topic' %}" method='post'>
2 {% csrf_token %}
3 {{ form.as_p }}
4 <button name="submit">add topic</button>
</form>
{% endblock content %}
這個模板繼承了base.html,因此其基本結(jié)構(gòu)與項目“學習筆記”的其他頁面相同。在1處, 我們定義了一個HTML表單。實參action告訴服務(wù)器將提交的表單數(shù)據(jù)發(fā)送到哪里,這里我們將 它發(fā)回給視圖函數(shù)new_topic()。實參method讓瀏覽器以POST請求的方式提交數(shù)據(jù)。
Django使用模板標簽{% csrf_token %}(見2)來防止攻擊者利用表單來獲得對服務(wù)器未經(jīng) 授權(quán)的訪問(這種攻擊被稱為跨站請求偽造)。在3處,我們顯示表單,從中可知Django使得完 成顯示表單等任務(wù)有多簡單:我們只需包含模板變量{{ form.as_p }},就可讓Django自動創(chuàng)建顯 示表單所需的全部字段。修飾符as_p讓Django以段落格式渲染所有表單元素,這是一種整潔地顯 示表單的簡單方式。
Django不會為表單創(chuàng)建提交按鈕,因此我們在4處定義了一個這樣的按鈕。
6. 鏈接到頁面new_topic
接下來,我們在頁面topics中添加一個到頁面new_topic的鏈接:
topics.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
--snip--
</ul>
<a href="{% url 'learning_logs:new_topic' %}">Add a new topic:</a>
{% endblock content %}
這個鏈接放在了既有主題列表的后面。圖19-1顯示了生成的表單。請使用這個表單來添加幾 個新主題。
19.1.2 添加新條目
現(xiàn)在用戶可以添加新主題了,但他們還想添加新條目。我們將再次定義URL,編寫視圖函數(shù) 和模板,并鏈接到添加新條目的網(wǎng)頁。但在此之前,我們需要在forms.py中再添加一個類。
1. 用于添加新條目的表單
我們需要創(chuàng)建一個與模型Entry相關(guān)聯(lián)的表單,但這個表單的定制程度比TopicForm要高些:
forms.py
from django import forms
from .models import Topic, Entry
class TopicForm(forms.ModelForm):
--snip--
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['text']
1 labels = {'text': ''}
2 widgets = {'text': forms.Textarea(attrs={'cols': 80})}
我們首先修改了import語句,使其除導入Topic外,還導入Entry。新類EntryForm繼承了forms.ModelForm,它包含的Meta類指出了表單基于的模型以及要在表單中包含哪些字段。這里也 給字段'text'指定了一個空標簽(見1)。
在2處,我們定義了屬性widgets。小部件(widget)是一個HTML表單元素,如單行文本框、 多行文本區(qū)域或下拉列表。通過設(shè)置屬性widgets,可覆蓋Django選擇的默認小部件。通過讓 Django使用forms.Textarea,我們定制了字段'text'的輸入小部件,將文本區(qū)域的寬度設(shè)置為80 列,而不是默認的40列。這給用戶提供了足夠的空間,可以編寫有意義的條目。
2. URL模式new_entry
在用于添加新條目的頁面的URL模式中,需要包含實參topic_id,因為條目必須與特定的主 題相關(guān)聯(lián)。該URL模式如下,我們將它添加到了learning_logs/urls.py中:
urls.py
--snip--
urlpatterns = [
--snip--
# 用于添加新條目的頁面
url(r'^new_entry/(?P<topic_id>\d+)/$', views.new_entry, name='new_entry'),
]
這個URL模式與形式為http://localhost:8000/new_entry/id/的URL匹配,其中id是一個與 主題ID匹配的數(shù)字。代碼(?P\d+)捕獲一個數(shù)字值,并將其存儲在變量topic_id中。請 求的URL與這個模式匹配時,Django將請求和主題ID發(fā)送給函數(shù)new_entry()。
3. 視圖函數(shù)new_entry()
視圖函數(shù)new_entry()與函數(shù)new_topic()很像:
views.py
from django.shortcuts import render
--snip--
from .models import Topic
from .forms import TopicForm, EntryForm
--snip--
def new_entry(request, topic_id):
"""在特定的主題中添加新條目"""
1 topic = Topic.objects.get(id=topic_id)
2 if request.method != 'POST':
# 未提交數(shù)據(jù),創(chuàng)建一個空表單
3 form = EntryForm()
else:
# POST提交的數(shù)據(jù),對數(shù)據(jù)進行處理
4 form = EntryForm(data=request.POST)
if form.is_valid():
5 new_entry = form.save(commit=False)
6 new_entry.topic = topic
new_entry.save()
7 return HttpResponseRedirect(reverse('learning_logs:topic',
args=[topic_id]))
context = {'topic': topic, 'form': form}
return render(request, 'learning_logs/new_entry.html', context)
我們修改了import語句,在其中包含了剛創(chuàng)建的EntryForm。new_entry()的定義包含形參 topic_id,用于存儲從URL中獲得的值。渲染頁面以及處理表單數(shù)據(jù)時,都需要知道針對的是哪 個主題,因此我們使用topic_id來獲得正確的主題(見1)。
在2處,我們檢查請求方法是POST還是GET。如果是GET請求,將執(zhí)行if代碼塊:創(chuàng)建一 個空的EntryForm實例(見3)。如果請求方法為POST,我們就對數(shù)據(jù)進行處理:創(chuàng)建一個EntryForm 實例,使用request對象中的POST數(shù)據(jù)來填充它(見4);再檢查表單是否有效,如果有效,就設(shè) 置條目對象的屬性topic,再將條目對象保存到數(shù)據(jù)庫。
調(diào)用save()時,我們傳遞了實參commit=False(見5),讓Django創(chuàng)建一個新的條目對象,并 將其存儲到new_entry中,但不將它保存到數(shù)據(jù)庫中。我們將new_entry的屬性topic設(shè)置為在這個 函數(shù)開頭從數(shù)據(jù)庫中獲取的主題(見6),然后調(diào)用save(),且不指定任何實參。這將把條目保 存到數(shù)據(jù)庫,并將其與正確的主題相關(guān)聯(lián)。
在7處,我們將用戶重定向到顯示相關(guān)主題的頁面。調(diào)用reverse()時,需要提供兩個實參: 要根據(jù)它來生成URL的URL模式的名稱;列表args,其中包含要包含在URL中的所有實參。在這 里,列表args只有一個元素——topic_id。接下來,調(diào)用HttpResponseRedirect()將用戶重定向到 顯示新增條目所屬主題的頁面,用戶將在該頁面的條目列表中看到新添加的條目。
4. 模板new_entry
從下面的代碼可知,模板new_entry類似于模板new_topic:
new_entry.html
{% extends "learning_logs/base.html" %}
{% block content %}
1 <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>
<p>Add a new entry:</p>
2 <form action="{% url 'learning_logs:new_entry' topic.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name='submit'>add entry</button>
</form>
{% endblock content %}
我們在頁面頂端顯示了主題(見1),讓用戶知道他是在哪個主題中添加條目;該主題名也 是一個鏈接,可用于返回到該主題的主頁面。
表單的實參action包含URL中的topic_id值,讓視圖函數(shù)能夠?qū)⑿聴l目關(guān)聯(lián)到正確的主題(見 2)。除此之外,這個模板與模板new_topic.html完全相同。
5. 鏈接到頁面new_entry
接下來,我們需要在顯示特定主題的頁面中添加到頁面new_entry的鏈接:
topic.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topic: {{ topic }}</p>
<p>Entries:</p>
<p>
<a href="{% url 'learning_logs:new_entry' topic.id %}">add new entry</a>
</p>
<ul>
--snip—
</ul>
{% endblock content %}
我們在顯示條目前添加鏈接,因為在這種頁面中,執(zhí)行的最常見的操作是添加新條目。圖19-2 顯示了頁面new_entry?,F(xiàn)在用戶可以添加新主題,還可以在每個主題中添加任意數(shù)量的條目。 請在一些既有主題中添加一些新條目,嘗試使用一下頁面new_entry。
19.1.3 編輯條目
下面來創(chuàng)建一個頁面,讓用戶能夠編輯既有的條目。
1. URL模式edit_entry
這個頁面的URL需要傳遞要編輯的條目的ID。修改后的learning_logs/urls.py如下:
urls.py
--snip--
urlpatterns = [
--snip--
# 用于編輯條目的頁面
url(r'^edit_entry/(?P<entry_id>\d+)/$', views.edit_entry,
name='edit_entry'),
]
在URL(如http://localhost:8000/edit_entry/1/)中傳遞的ID存儲在形參entry_id中。這個URL 模式將預期匹配的請求發(fā)送給視圖函數(shù)edit_entry()。
2. 視圖函數(shù)edit_entry()
頁面edit_entry收到GET請求時,edit_entry()將返回一個表單,讓用戶能夠?qū)l目進行編 輯。該頁面收到POST請求(條目文本經(jīng)過修訂)時,它將修改后的文本保存到數(shù)據(jù)庫中:
views.py
from django.shortcuts import render
--snip--
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
--snip--
def edit_entry(request, entry_id):
"""編輯既有條目"""
1 entry = Entry.objects.get(id=entry_id)
topic = entry.topic
if request.method != 'POST':
# 初次請求,使用當前條目填充表單
2 form = EntryForm(instance=entry)
else:
# POST提交的數(shù)據(jù),對數(shù)據(jù)進行處理
3 form = EntryForm(instance=entry, data=request.POST)
if form.is_valid():
4 form.save()
5 return HttpResponseRedirect(reverse('learning_logs:topic',
args=[topic.id]))
context = {'entry': entry, 'topic': topic, 'form': form}
return render(request, 'learning_logs/edit_entry.html', context)
關(guān)于“Python”的核心知識點整理大全37-CSDN博客
關(guān)于“Python”的核心知識點整理大全25-CSDN博客文章來源:http://www.zghlxwxcb.cn/news/detail-820035.html
關(guān)于“Python”的核心知識點整理大全12-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-820035.html
往期快速傳送門??(在文章最后):
感謝大家的支持!歡迎訂閱收藏!專欄將持續(xù)更新!
到了這里,關(guān)于關(guān)于“Python”的核心知識點整理大全56的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!