2025年《Tango with Django》-第7章 表单

《Tango with Django》-第7章 表单表单 这一章节中 我们将学习如何通过 web 表单获取数据 根据 django 关于表单的官方文档 表单处理通过如下功能 自动生成表单控件展现 HTML 表单 比如文本框或日期选择器 检查提交的数据是否违反了一系列验证规则 一旦出现错误重新展现一个表单

大家好,我是讯享网,很高兴认识大家。

表单

这一章节中,我们将学习如何通过web表单获取数据。根据django关于表单的官方文档,表单处理通过如下功能:
➊自动生成表单控件展现HTML表单(比如文本框或日期选择器);
➋检查提交的数据是否违反了一系列验证规则;
➌一旦出现错误重新展现一个表单;
➍将提交的表单数据转换成相关的python数据类型。
使用django表单功能的优点之一就是创建HTML表单时能为你节省很多时间和麻烦。

7.1 基本流程

创建表单并处理用户输入的基本步骤如下所示:
➊如果你还没有在django应用目录里创建forms.py文件的话,先创建一个用来存储与表单相关的类。
➋为每个你希望要表示成表单的模型创建一个ModelForm类。
➌按照你的需求设计表单。
➍创建一个视图处理表单

  • 包括显示表单
  • 保存表单数据
  • 当用户在表单中提交不正确的数据(或未提交数据)时,标记会发生的错误。

7.2 网页和分类表单

定义ModelForm 的子类

from django import forms from rango.models import Page,Category class CategoryForm(forms.ModelForm): name = forms.CharField(max_length=128,help_text="Please enter the category name.") views= forms.IntegerField(widget=forms.HiddenInput(),initial=0) likes = forms.IntegerField(widget=forms.HiddenInput(),initial=0) slug = forms.CharField(widget=forms.HiddenInput(),required=False) class Meta: model = Category fields = ('name',) class PageForm(forms.ModelForm): title = forms.CharField(max_length=128,help_text="Please enter the title of the page.") url = forms.URLField(max_length=200,help_text="Please enter the URL of the page.") views = forms.IntegerField(widget=forms.HiddenInput(),initial=0) class Meta: model = Page exclude = ('category',) # def clean(self): # clean_data = self.cleaned_data # url = cleaned_data.get('url') # if url and not url.startswith('http://'): # url = 'http://' + url # clearn_data['url'] = url # return clearn_data 

讯享网

编写添加分类视图

在CategoryForm类的定义中,我们已经创建了一个新视图展现表单并处理提交上来的表单数据。添加如下代码到rango/views.py。

讯享网from rango.forms import CategoryForm def add_category(request): form = CategoryForm() if request.method == 'POST': form = CategoryForm(request.POST) if form.is_valid(): form.save(commit=True) return index(request) else: print(form.errors) return render(request,'rango/add_category.html',{ 
   'form':form}) 
  • 展示一个新的空的增加分类的表单;
  • 将用户提交的表单数据保存到相应的模型中并渲染到rango的主页上;
  • 如果出现错误,会重新展示带错误的表单。

注意调用render()的那一行,我们引用了一个新的叫add_category.html的模板。这个模板会包含一些与表单相关的模板代码和HTML。

创建添加分类页面的模板

创建文件templates/rango/add_category.html,并填写如下代码。

<!DOCTYPE html> <html> <head> <title>Rango</title> </head> <body> <h1>Add a Category</h1> <div> <form id="category_form" method="post" action="/rango/add_category/"> { 
   % csrf_token %} { 
   % for hidden in form.hidden_fields %} { 
   { 
    hidden }} { 
   % endfor %} { 
   % for field in form.visible_fields %} { 
   { 
    field.errors }} { 
   { 
    field.help_text }} { 
   { 
    field }} { 
   % endfor %} <input type="submit" name="submit" value="Create Category"/> </form> </div>> </body> </html> 

你应该注意到这个代码段{% csrf_token %}。这是一个跨站请求伪造令牌,用来保护在随后提交表单时启动的HTTP的POST请求。django框架需要显式列出CSRF令牌。如果在表单中忘了加上一个CSRF令牌,提交表单时就有可能报错。

映射添加分类视图

现在我们需要将add_category()视图函数映射到URL上。在模板中,我们在表单的action属性里使用了/rango/add_category,现在我们需要创建一个从URL到视图的映射了。在rango/urls.py中,按照如下代码修改URL模式。

讯享网from django.conf.urls import url from rango import views urlpatterns = [ url(r'^$',views.index,name='index'), url(r'^add_category/$',views.add_category,name='add_category'), url(r'^category/(?P<category_name_slug>[\w\-]+)/$',views.show_category, name='show_category'), #url(r'about/$', views.about, name='about'), ] 

修改首页视图

最后一步让我们在index主页上添加一个链接,通过这个链接可以让我们直接的添加分类。编辑模板rango/index.html,如下所示,在about链接的div元素里添加一个超链接。


讯享网

 <div> <a href="/rango/add_category/">Add a New Category</a><br /> </div> 

效果检验

在这里插入图片描述
在这里插入图片描述

清理表单数据

在某些场景中,用户有可能输入了一些不完全正确的数据。我们可以重写ModelForm类中定义的clean()方法。这个方法在将表单数据保存到新的模型实例之前被调用,因此给我们提供了一个逻辑空间插入代码用来验证甚至是修复用户输入的表单数据,我们可以检查用户输入的url值是否以http://开头,如果不是,我们可以为用户的输入预添加http://。

讯享网 def clean(self): clean_data = self.cleaned_data url = cleaned_data.get('url') if url and not url.startswith('http://'): url = 'http://' + url clearn_data['url'] = url return clearn_data 

7.3 练习

在添加分类表单中如果不输入分类名称会发生什么?

在这里插入图片描述

如果添加的分类已经存在会发生什么?

在这里插入图片描述

如果访问不存在的分类会发生什么?后文有提示。

在这里插入图片描述

定义 ModelForm 子类时,我们为某些字段设定了 max_length 参数,这与模型中的验证重复了。想想如何重构,以免重复指定 max_length 值?

让用户能在分类中添加网页。参见下面的示例代码和提示。

from rango.forms import PageForm def add_page(request,category_name_slug): try: category = Category.objects.get(slug = category_name_slug) except Category.DoesNotExist: category = None form = PageForm() if request.method == 'POST': form = PageForm(request.POST) if form.is_valid(): if category: page = form.save(commit=False) page.category = category page.views = 0 page.save() return show_category(request,category_name_slug) else: print(form.errors) context_dict = { 
   'form':form,'category':category} return render(request,'rango/add_page.html',context_dict) 

❏ 创建一个模板,rango/add_page.html

讯享网<!DOCTYPE html> <html> <head> <title>Rango - Add Page</title> </head> <body> { 
   % if category %} <h1>Add a Page to { 
   { 
   category.name}}</h1> <form id="page_form" method="post" action="/rango/category/{ 
   { category.slug }}/add_page/"> { 
   % csrf_token %} { 
   % for hidden in form.hidden_fields %} { 
   { 
    hidden }} { 
   % endfor %} { 
   % for field in form.visible_fields %} { 
   { 
    field.errors }} { 
   { 
    field.help_text }} { 
   { 
    field }} { 
   % endfor %} <input type="submit" name="submit" value="Add Page" /> </form> { 
   % else %} The specified category does not exist! { 
   % endif%} </body> </html> 

❏ 添加一个 URL 映射

from django.conf.urls import url from rango import views urlpatterns = [ url(r'^$',views.index,name='index'), url(r'^add_category/$',views.add_category,name='add_category'), url(r'^category/(?P<category_name_slug>[\w\-]+)/$',views.show_category, name='show_category'), #url(r'about/$', views.about, name='about'), url(r'^category/(?P<category_name_slug>[\w\-]+)/add_page/$', views.add_page, name='add_page'), ] 

❏ 更新分类页面的模板和视图,加上添加网页链接

讯享网<a href="/rango/category/{ 
   {category.slug}}/add_page/">Add Page</a> <br/> 

在这里插入图片描述

小讯
上一篇 2025-02-15 16:40
下一篇 2025-03-29 23:12

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/124579.html