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--
每个条目都有一个用于对其进行编辑的链接
推荐阅读
-
为什么要用trim()修剪用户输入的数据?解决方法
-
select 下拉框如何可以选择option里面的值,也可以用户自己输入啊?_html/css_WEB-ITnose
-
13. 编写一个程序,提示用户输入3组数,每组数包含5个double类型的数(假设用户都正确地响 应,不会输入非数值数据)。该程序应完成下列任务。
-
C#实现对用户输入数据进行校验的类实例
-
MySQL 客户端不输入用户名和密码直接连接数据库的2个方法
-
php中filter函数验证、过滤用户输入的数据
-
C#实现对用户输入数据进行校验的类实例
-
php中filter函数验证、过滤用户输入的数据
-
php 字符过滤类,用于过滤各类用户输入的数据
-
【Web API系列教材】1.3 — 实战:用ASP.NET Web API和Angular.js创建单页面应用程序(上)