19.1.1 添加新主题
让用户输入并提交信息的页面都是表单,那怕它看起来不像表单。
用户输入信息时,我们需要进行验证,确认提供的信息时正确的数据类型,且不是恶意的信息。
在Django中,创建表单的最简单方式是使用ModelForm,创建一个名为forms.py的文件,
将其存储到models.py所在的目录中
node2:/django/mysite/learning_log/learning_logs#cat forms.py
from django import forms
from .models import Topic
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text':''}
我们首先导入了模块forms以及要使用的模型Topic.我们定义了一个名为TopicForm的类,它继承了forms.ModelForm
最简单的ModelForm版本只包含一个内嵌的Meta类,它告诉Django根据哪个模型创建表单,以及在表单中包含哪些字段
在2处,我们根据模型Topic创建一个表单,该表单只包含字段text
2.URL 模式new_topic:
这个新网页的URL应简短而具有描述性,因此当用户要添加新主题时,
我们将切换到http://localhost:8000/new_topic/ 下面是网页new_topic的URL模式,我们将其添加到learn_logs/urls.py
node2:/django/mysite/learning_log/learning_logs#cat urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$',views.index,name='index'),
url(r'^topics/$',views.topics,name='topics'),
url(r'^new_topic/$',views.new_topic,name='new_topic'),
url(r'^topics/(?P<topic_id>d+)/$',views.topic,name='topic'),
这个URL模式将请求交给视图函数new_topic(),接下来我们将编写这个函数
3.视图函数new_topic()
函数new_topic()需要处理两种情形,刚进入new_topic网页(在这种情况下,它应显示一个空表单):
对提交的表单数据进行处理,并将用户重定向到网页topics
node2:/django/mysite/learning_log/learning_logs#cat views.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.shortcuts import render
from .models import Topic
from .forms import TopicForm
# Create your views here.
def index(request):
return render(request,'learning_logs/index.html')
def topics(request):
print 'call topics'
topics = Topic.objects.order_by('date_added')
context = {'topics':topics}
return render(request,'learning_logs/topics.html',context)
def new_topic(request):
if request.method != 'POST':
form = TopicForm()
else:
#POST提交的数据,对数据进行处理
form = TopicForm(request.POST)
if form.is_valid():
form.save()
print '11111111111111'
return HttpResponseRedirect(reverse('learning_logs:topics'))
print '2222222222222'
context = {'form' : form}
return render(request,'learning_logs/new_topic.html',context)
def topic(request,topic_id):
print topic_id
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic':topic,'entries':entries}
print context
return render(request,'learning_logs/topic.html',context)
我们导入了HttpResponseRedirect类,用户提交主题后我们将使用这个类将用户重定向到topics网页
return HttpResponseRedirect(reverse('learning_logs:topics'))
4.GET请求和POST请求
创建Web应用程序时,将用到的两种主要请求类型是GET请求和POST请求。
函数new_topic()将请求对象作为参数,用户初次请求该网页时,其浏览器将发送GEY请求:
用户填写并提交表单时,其浏览器将发送POST请求。根据请求的类型
我们可以确定用户请求的是空表单(GET请求)还是要求对填写好的表单进行处理
1处的测试确定请求方法是GET还是POST,如果请求方法不是POST,请求就可能是GET
因此我们需要返回一个空表单
如果请求方法为POST,将执行else代码块,对提交的表单数据进行处理。
我们使用用户输入的数据(它们存储在request.POST中)创建一个TopicForm实例
要将提交的信息保存到数据库,必须先检查确定它们是有效的
函数is_valid()核实用户填写了所有必不可少的字段(表单字段默认都必不可少的)
且输入的数据与要求的字段类型一致
5.模板new_topic:
下面来创建新模板new_topic.html,用于显示我们刚创建的表单:
node2:/django/mysite/learning_log/learning_logs#cat templates/learning_logs/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,因此其基本结构与项目"学习笔记”的其他页面相同
在1处,我们定义了一个HTML表单。实参action告诉服务器将提交的表单数据发送到哪里,
这里我们将它发回给视图函数new_topic()
实参method让浏览器以POST请求的方式提交数据
Django使用模板标签{% csrf_token %} 来防止攻击者利用表单来获得对服务器未经授权的访问
6 连接到页面new_topic
接下来,我们在页面topics中添加一个到页面new_topic的连接
node2:/django/mysite/learning_log/learning_logs#cat templates/learning_logs/topics.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
</ul>
<a href="{% url 'learning_logs:new_topic' %}">Add a new topic:</a>
{% endblock content %}