Web應用程序1.3——用戶輸入數據

一、添加新主題

首先讓用戶添加新主題,創建基於表單的方法幾乎與前面創建網頁一樣,定義一個URL,編寫一個視圖函數並編寫一個模板。

一個人主要差別是需要導入含表單的模塊forms.py。

1.用於添加主題的表單

在Django中,創建表單最簡單的方法是使用ModelForm。該表單只含字段text,並不要讓字段生成標籤。

forms.py

from django import forms

from .models import Topic

class TopicForm(forms.ModelForm):
	class Meta:
		model=Topic
		fields=['text']
		labels={'text':''}

2.URL模式new_topic

urls.py


urlpatterns=[
   --snip
    #用於添加新主題的網頁
    url(r'^new_topic/$',views.new_topic,name='new_topic'),]

這個URL模式將請求交給視圖函數new_topic()

3.視圖函數new_topic()

views.py

from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse

from .models import Topic
from .forms import TopicForm

--snip--
def new_topic(request):
	"""添加新主題"""
	if request.method!='POST':
		#未提交數據:創建一個新表單
		form=TopicForm()
	else:
		#POST提交的數據,對數據進行處理
		form=TopicForm(request.POST)
		if form.is_valid():
			form.save()
			return HttpResponseRedirect(reverse('learning_logs:topics'))
			
	context={'form':form}
	return render(request,'learning_logs/new_topic.html',context)

    我們導入了HttpResponseRedirect類,用戶提交主題後我們將使用這個類將用戶重定向到網頁topics。函數reverse()根據指定的URL模型確定URL,這意味着Django將在頁面被請求是生成URL。

4.GET請求和POST請求
    創建Wed應用程序時,主要有兩種請求:GET請求和POST請求。對於只從服務器讀取數據的頁面,使用GET請求;在用戶需要通過表單提交信息時,通常使用POST請求。
    new_topic()將請求對象作爲參數,用戶初次請求該網頁時,其瀏覽器發送GET請求,用戶填寫並提交表單時,其瀏覽器發送POST請求。如果是POST請求,我們先通過檢查確定它們是否有效的。如果有效,save()方法保存到數據庫保存頁面,就可以離開這個頁面了,在頁面topics中,用戶將在主題列表中看到剛輸入的主題。

5.模板new_topic

new_topic.html

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

{% block content %}
  <p>Add a new topic:</p>
  
  <form action="{% url 'learning_logs:new_topic' %}" method='post'>
	{% csrf_token %}
	{{ form.as_p }}
	<button name="submit">add topic</button>
  </form>
  
{% endblock content %}

    模板首先繼承base.html ,我們定義了一個HTML表單,其中實參action告訴服務器將提交的表單數據發送到哪裏,這裏將發送到視圖函數new_topic()。實參method讓瀏覽器以POST請求的方式提交數據,Django使用模板標籤{% csrf_token %}來防止攻擊者利用表單來獲得對服務器未經授權的訪問。{{form.as_p}}可以讓Django自動創建顯示錶單所需的全部字段,修飾符as_p讓Django以段落的格式渲染所有表單元素。

6.鏈接到頁面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 %}

由於添加新主題的頁面

二、添加新條目

1.用於添加新條目的表單

我們創建一個與模型Entry相關聯的表單。

forms.py

from django import forms

from .models import Topic,Entry
	
class EntryForm(forms.ModelForm):
	class Meta:
		model=Entry
		fields=['text']
		labels={'text':''}
		widgets={'text':forms.Textarea(attrs={'cols':80})}

新類EntryForm繼承了forms.ModelForm。我們定義了屬性widgets,小部件(widget)是一個HTML表單元素,如單行文本框、多行文本區域或下拉列表。通過設置屬性widgets,可覆蓋Django選擇的默認小部件。通過讓Django使用froms.Textarea,我們定製了字段‘text’的輸入小部件,將文本區域的寬度設置爲80列,而不是默認的40列。

2.URL模式new_entry

在用於添加新條目的頁面的URL模式中,需要包含實參topic_id,因爲條目必須與特定的主題相關聯。

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匹配的數字。代碼(?P<topic_id>\d+)捕獲一個數字值,並將其儲存在變量topic_id中。請求的URL與這個模式匹配時,Django將請求和主題ID發送給函數new_entry()

3.視圖函數new_entry()

views.py

from django.shortcuts import render
--snip--

from .models import Topic
from .forms import TopicForm,EntryForm

--snip--
def new_entry(request,topic_id):
	"""在特定的主題中添加新條目"""
	topic=Topic.objects.get(id=topic_id)
	
	if request.method != 'POST':
		#未提交數據,創建一個空表單
		form=EntryForm()
		
	else:
		#POST提交的數據,對數據進行處理
		form=EntryForm(data=request.POST)
		if form.is_valid():
			new_entry=form.save(commit=False)
			new_entry.topic=topic
			new_entry.save()
			return HttpResponseRedirect(reverse('learning_logs:topic',
			                            args=[topic_id]))
			
	context={'topic':topic,'form':form}
	return render(request,'learning_logs/new_entry.html',context)

在調用save()時,我們傳遞了實參commit=False,讓Django創建一個新的條目對象,並將其儲存在new_entry中,但不將它保存在數據庫中。

4.模板new_entry

new_entry.html

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

{% block content %}

  <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>
  
  <p>Add a new entry:</p> 
  <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 %}

5.鏈接到頁面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 %}

頁面new_entry

三、編輯條目

1.URL模式edit_entry

urls.py

--snip--
urlpatterns=[
    --snip--
    #用於編輯條目的頁面
    url(r'^edit_entry/(?P<entry_id>\d+)/$',views.edit_entry,
        name='edit_entry'),]

2.視圖函數edit_entry()

views.py

def edit_entry(request, entry_id):
	"""編輯既有條目"""
	entry = Entry.objects.get(id = entry_id) #獲得用戶要修改的條目對象和與該條目相關的主題
	topic = entry.topic
 
	if request.method != 'POST':
		""" 初次請求,使用當前條目填充表單"""
		form = EntryForm(instance = entry)
	else:
		""" POST提交的數據,對數據進行處理 """
		form = EntryForm(instance = entry, data = request.POST)
		if form.is_valid():
			form.save() 
			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)

3.模板edit_entry

edit_entry.html

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

{% block content %}

  <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>
  
  <p>Edit entry:</p> 
  <form action="{% url 'learning_logs:edit_entry' entry.id %}" method='post'>
	{% csrf_token %}
	{{ form.as_p }}
	<button name="submit">save changes</button>
  </form>
  
{% endblock content %}

4.鏈接到頁面edit_entry

topic.html

--snip--
  {% for entry in entries %}
    <li>
		<p>{{ entry.date_added|date:'M d,Y H:i' }}</p>
		<p>{{ entry.text|linebreaks }}</p>
		<p>
			<a href="{% url 'learning_logs:edit_entry' entry.id %}">edit entry</a>
		</p>
	</li>
 --snip--

每個條目都有一個用於對其進行編輯的鏈接

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