现在用户可以添加新主题了,但他们还想添加新条目。
我们将再次定义URL,编写视图函数和模板,并连接到添加新条目的网页。
但在此之前,我们需要在forms.py中再添加一个类
1.用于添加新条目的表单
我们需要创建一个与模型Enrey相关联的表单,但这个表单的定制成都比TopicForm更高些:
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['text']
labels = {'text':''}
widgets = {'text':forms.Textarea(attrs={'cols':80})}
from django import forms
from .models import Topic,Entry
我们首先修改了import 语句,使其除导入Topic外,
还导入了Entry.
新类EntryForm继承了forms.ModelForm,
它包含了Meta类指出了表单基于的模型以及要在表单中包含哪些字段.
这里也给字段'text' 指定了一个空标签
在2处,我们定义了属性widgets. 小部件(widget)是一个HTML表单元素,
如单行文本框,多行文本区域或下拉列表。
通过设置属性widgets,可覆盖Django选择的默认小部件。
通过让Django使用forms.Textarea,我们定制了字段'text',
将文本区域的宽度设置为80列,而不是默认的40列。
2.URL模式new_entry
在用于添加条目的页面的URL模式中,需要包含实参topic_id,因为条目必须与特定的主题相关联。
该URL模式如下,我们将它添加到learning_logs/urls.py中
node2:/django/mysite/learning_log/learning_logs#vim 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(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()
视图函数new_entry与函数new_topic()很像
def new_entry(request,topic_id):
topic = Topic.objects.get(id=topic_id)
if request.method != 'POST':
#未提交数据,创建一个空表单
print 'aaaaaaaaaaaaaaaaaaaaaaaa'
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)
node2:/django/mysite/learning_log/learning_logs#vim 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,EntryForm
我们修改了import语句,在其中包含了刚创建的EntryForm。
new_entry()的定义包含形参topic_id,用于存储从URL获得的值。
渲染页面以及处理表单数据时,都需要知道针对的哪个主题,
因此我们使用topic_id来获得正确的主题。
在2处,我们检查请求方式POST还是GET.如果是GET请求,将执行if代码块:
创建一个空的EntryForm实例。如果请求方法为POST,我们就对数据进行处理:
创建一个EntryForm实例,使用request对象中的POST数据来填充它:
在检查表单是否有效,如果有效,就设置条目对象的属性topic,
再将条目对象保存到数据库。
调用save()时,我们传递了实参commit=False,让Django创建一个新的条目对象,
并将其存储到new_entry中,但不将它保存到数据库中。
4.模板new_entry
从下面的代码可知,模板new_entry类似于模板new_topic:
node2:/django/mysite/learning_log/learning_logs/templates/learning_logs#cat 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
接下来,我们需要在显示特定主题的页面中添加到页面new_entry的连接:
topic.html
node2:/django/mysite/learning_log/learning_logs/templates/learning_logs#cat 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 %}