现在用户可以添加新主题了,但他们还想添加新条目。

我们将再次定义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 %}