一、使用情景
在我们的后台管理页面中需要一个表单来提交和修改博客,按照上一篇讲的,我们可以这么使用:
先定义一个 Form类,包括标题、标签和内容三个字段:
class ArticleForm(forms.Form):
title = forms.CharField(label='标题', max_length=50)
tags = forms.CharField(label='标签', max_length=50)
content = TextFiled(label='内容')
然后在页面中就可以直接使用 form,在提交表单时,我们还需要将各个字段赋值给 model的对应字段。
在修改文章的页面我们需要先将表格填充好,再渲染页面。
这时我们的表单还只有几个字段,工作量并不大,但是如果表单的字段增加到十几个,工作量就有点大了。
幸好 Django为我们提供了 ModelForm
类,可以根据已存在的 Model类来自动地创建 Form
类。
二、使用 ModelForm
使用 ModelForm
很简单,我们只需要创建一个元类并给对应的属性赋值即可,如下:
class ArticleForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'tags', 'content']
我们可以通过 fields
来确定需要输入的字段,也可以通过 exclude
来设置不需要输入的字段。
这样当我们提交表单之后,只需要调用 ArticleForm
的 save
方法即可将添加的博客保存到数据库中去。
不过我们这里有两个字段没有添加到 form表单中去,所以在调用 save
方法时会报错,这时只需重载 save
方法即可:
class ArticleForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'tags', 'content']
def save(self, commit=True):
key = abs(hash(self.instance.title))
date = datetime.datetime.now().strftime('%Y-%m-%d')
self.instance.key = key
self.instance.date = key
self.instance.save()
return self.instance
在视图函数中我们可以这样使用:
def addArticle(request):
if request.method == 'GET':
form = ArticleForm()
return render(
request,
'myblog/add_article.html',
{'pagedata':
{'form':form}
}
)
elif request.method == 'POST':
form = ArticleForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('article_list'))
else:
return render(
request,
'myblog/add_article.html',
{'pagedata':
{'form': form}
}
)
在编辑文章的页面,我们可以直接将查询到的 Post
类传递给 ArticleForm
的 instance
参数。
instance
参数将会赋值给 ArticleForm
的 instance
属性,我们上面重载 save
方法时就用到了 instance
属性。
def modifyArticle(request, key):
if request.method == 'GET':
post_list = Post.objects.filter(key=key)
if len(post_list) == 0:
return HttpResponse('文章不存在')
else:
article_form = ArticleForm(instance=post_list[0])
... ...
如果想指定某个字段的样式,可以通过 Meta
类的 widgets
属性来指定,如下:
class TagInput(widgets.Input):
input_type = 'text'
template_name = 'myblog/widgets/input.html'
class ArticleForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'tags', 'content']
widgets = {
'tags': TagInput
}
def save(self, commit=True):
... ...
我们来看看效果: