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--

每个条目都有一个用于对其进行编辑的链接

猜你喜欢

转载自blog.csdn.net/IMWTJ123/article/details/82193348