当前位置: 首页 > 编程笔记 >

在Django同1个页面中的多表单处理详解

韦胜泫
2023-03-14
本文向大家介绍在Django同1个页面中的多表单处理详解,包括了在Django同1个页面中的多表单处理详解的使用技巧和注意事项,需要的朋友参考一下

快速上手Django实现项目

近期公司在做1个海淘的项目,APP为pylot。由于时间比较赶,加上隔壁那哥们不在,只能自己挑大梁了。结果,当项目做出来之后,被领导狠狠的批了一顿,说怎么用django写,你能解决Django的内存问题吗,你能解决并发的问题吗?Django那么重。

然后我只好回答说,正是因为它重,所以人家拿来写大型项目。虽然这里不是为了上面这2个问题的,而是来说下如何快速开发原型的问题。

对于Django这样基于模型的Web框架,实话说真的解决了很多繁琐的工作。由于它1个模型对应1张表,因此只要很短暂的时间就把原型给弄完了。实际上,我用Django主要是不用被页面浪费我的时间,这样我就可以专心写API那方面了。

结果,公司这个项目除了自己可以看到外,还要实现1个B端的需求,而我此时的后台功能已经完成了,这可以如何是好。而区别在于只能让注册的用户只能看到属于它自己的订单,而其他不变。

于是上官方文档看了下表单的教程,看到1个ModelForm的玩意,通过它可以将后台的表单直接渲染出来,而后在ModelForm类中通过instance关键字可以将对应模型直接渲染出来,这样花了1个星期的时间就把API、B端和公司的后台完成了,效率还算比较高。

下面说下如何通过Django快速实现项目:

  1. 实际上分解问题很关键,把问题按等级划分有助于加快开发速度
  2. 把不怎么会写的代码先跳过,使用繁琐的方式先写上去,后面再用其内建的方式来替换
  3. 不要紧张,一定要保持淡定,不然你会发现你完全写不出代码
  4. 不要看官方文档,因为写的啰嗦又难找到重点
  5. 带着问题在网上搜索答案,如果某个方式不行就换种思路去做,比如要实现1个多对多的关系的HTML组件,直接找第3方插件而不是看文档实现

相信如何能做到以上几点,才能把django的效率发挥出来。下面来看看本文的详细介绍吧。

Django同1个页面中的多表单处理

关于在同1个页面多个表单提交的问题,实际上是项目中遇到的1个小问题。关于这个问题,主要有2个需要解决的问题:

  1. 多个表单的渲染问题
  2. 多个表单提交时外键的处理问题

下面我们分别进行说明。

当时在建模的时候使用了类似如下的方式:

from django.db import models 

class Store(models.Model): 
 name = models.CharField('名称', max_length=20) 
 first = models.FloatField('首重') 
 additional = models.FloatField('次重') 
 img = models.ImageField('图片', upload_to='store/1') 

class Depot(models.Model): 
 s_name = models.ForeignKey(Store, verbose_name='仓库') 
 src = models.CharField('始发地', max_length=20) 
 dest = models.CharField('目的地', max_length=20) 
 days = models.PositiveSmallIntegerField('需要的天数') 

class Address(models.Model): 
 s_name = models.ForeignKey(Store, verbose_name='仓库') 
 country = models.CharField('国家', max_length=20) 
 state = models.CharField('省份', max_length=10) 
 city = models.CharField('城市', max_length=10) 
 description = models.TextField('描述', blank=True)

在这里,1个仓库的数据主要由3个表组成,分别为它的一些基础信息,可以配送的范围、天数及其他一些附加信息组成。然后其页面如下所示:

多表单渲染

而公司的需求就是我们要在商户端上让客户在创建仓库时填写上述的内容,由于我比较懒,而公司给出的时间也不是很充裕,于是直接使用ModelForm来实现,而不需要一一的创建表单了。换句话说,我们要将多个模型表在同1个页面中渲染出来,对于这样的问题,主要有4种解决的方案:

  1. 在1个form组件中使用多个模型表单类
  2. 使用django提供的modelform_factory来解决
  3. 使用第3方插件django-betterforms或django-multipleformwizard这样的插件
  4. 使用元类,然后继承BaseForm进行表单的重写。

这里我们使用第1种解决方案来实现多个表单渲染的问题。

这里我们在forms模块下新建3个模型表单类:

from django.forms import ModelForm 
from models import Store, Address, Depot 

class StoreForm(ModelForm): 
 class Meta: 
 model = Store 
 fields = '__all__' 

class AddressForm(ModelForm): 
 class Meta: 
 model = Address 
 exclude = ['s_name'] 

class DepotForm(ModelForm): 
 class Meta: 
 model = Depot 
 exclude = ['s_name']

然后在视图中引入这3个表单:

from django.shortcuts import render_to_response, HttpResponseRedirect 
from django.template import RequestContext 
from forms import StoreForm, AddressForm, DepotForm 

def store_add(req): 
 if req.method == 'POST': 
 ... 
 else: 
 sf = StoreForm() 
 af = AddressForm() 
 df = DepotForm() 
 return render_to_response('store_add.html', { 
 'sf': sf, 'af': af, 'df': df, 
 }, context_instance=RequestContext(req))

默认情况下,我们先将对应的表单渲染出来先。在这里我们往模板中输出了多个变量,然后在模板中手动进行如下的处理:

<form action="" method='post' enctype='multipart/form-data'> 
 {% csrf_token %} 
 {{ sf.as_p }} 
 {{ df.as_p }} 
 {{ af.as_p }} 
 <input type="submit" value = "添加" /> 
</form>

在这里,我们在1个表单中输出多个表单,其页面如下所示:

可以看到其效果与后台的页面相差不是很大,只是没有对应的样式而已。

多表单提交外键处理

接着我们需要处理多个表单提交时的处理问题。

def store_add(req): 
 if req.method == 'POST': 
 sf = StoreForm(req.POST, req.FILES) 
 af = AddressForm(req.POST) 
 df = DepotForm(req.POST) 
 if sf.is_valid() and af.is_valid() and df.is_valid(): 
 sf.save() 
 df.save() 
 af.save() 
 return HttpResponseRedirect('store') 
 ...

在这里我们直接对这3个表单进行保存,结果出现了这样1个错误。

NOT NULL constraint failed: app_depot.s_name_id 

由于我们使用了1个外键进行了约束,而使用上述的方式会导致数据表中的s_name_id的字段数值为NULL,从而导致了错误。而上述的方式时直接就提交给数据库了,导致后面的外键无法被满足。

为了解决这个问题,我们采用延迟提交给数据库的方式:

def store_add(req): 
 if req.method == 'POST': 
 ... 
 if sf.is_valid() and af.is_valid() and df.is_valid(): 
 form = sf.save(commit=False) 
 sf.save() 
 dform = df.save(commit=False) 
 dform.s_name = form 
 dform.save() 
 aform = af.save(commit=False) 
 aform.s_name = form 
 aform.save() 
 return HttpResponseRedirect('store') 
 else: 
 ...

在这里,我们先让第1张表先不提交,将其保存为1个变量form中。而第2个张表也先不提交,我们将其实例的s_name修改为之前的第1张表返回的结果,然后再进行保存。这样我们就实现了多张表的依赖导致的问题了。最后我们使用重定向的方式将成功添加后的页面跳转到该商户的仓库列表中。

其跳转后的页面如下所示:

这样我们就解决了在1个页面提交多个表单的问题。实际关于Django在1个页面提交多个表单的问题,实际上问题不是很多,只要解决了渲染和提交时处理的问题,实际这个问题就迎刃而解了。重要的是如何拆分问题和解决问题的思路。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对小牛知识库的支持。

 类似资料:
  • 主要内容:在视图中使用表单在Django创建表单,类似于创建一个模型。 在这里,我们只需要从Django的类并继承此类属性表单字段。让我们在myapp文件夹中添加forms.py文件包含我们的应用程序的表单。我们将创建一个登录表单。 myapp/forms.py 由上可见,字段类型可以利用“widget”的参数到HTML渲染; 在我们的例子中,我们要隐藏密码,不会显示。在我们的例子中,想要隐藏密码而不用显示。 日期输入是D

  • 我正在尝试制作一个登录和注册页面,但问题是同一页面上的两个表单返回以下错误: HTML表单代码 控制器代码:

  • 问题内容: 请在问题上需要您的帮助。我的主页上有两个表格,我希望用户在不同的时间填写和提交。我的问题是,我只希望对它们两个都有一个处理页面。通常我可以在单独的页面中执行此操作。但我想知道是否可以在同一页面上进行。 好吧..如果我在操作页面上提交表单A,则不会为表单B的变量提供未定义的索引,该索引尚未提交,当然也不建议使用GET。 感谢您的时间和耐心等待。 问题答案: 这样做并非完全没有听说过。通常

  • 嗨,我试图使用chartjs可以在这个链接中找到www.chartjs.org 我试图用样本代码在同一页上画两个图表 我用两个不同的ID创建了两个不同的div 就像这样 那么在包括这一行之后: 我以这种方式创建了第一个图表: 第二张图表是这样的: 两个图表使用的数据与样本相同,所以没有什么变化,但如果我只画一个图表本身,它的工作原理很好,如果我把两个图表在同一时间,我只得到饼图 你能告诉我问题在哪

  • 问题内容: 如果用户未登录,我希望登录表单(来自django.contrib.auth的AuthenticationForm)出现在网站的每个页面上。当用户登录时,它们将被重定向到同一页面。如果有错误,该错误将与表格一起显示在同一页面上。 我想你需要一个上下文处理器来为每个模板提供表单。但是,那么你还需要每个视图来处理发布的表单吗?这是否意味着你需要创建一些中间件?我有点迷路了。 是否有接受的方法

  • 问题内容: 我在MySQL数据库中有几个临时表,它们共享相同的架构并具有动态名称。我将如何使用Django与这些表进行交互?一个模型可以从多个表中提取数据吗? 问题答案: 我相信,你可以创建一个工厂函数,该函数将通过动态db_table返回你的模型。 编辑:每次调用此函数时,Django不会创建类属性的新实例。为它创建一个新实例取决于类的名称(Django必须将其缓存在某个地方)。元类可用于在运行

  • > 第一种形式是客户可以通过数据库中的id值作为单选按钮获取所有产品 客户endpoint击提交。 PHP询问提交按钮的集合名称 如果是设置,它呼应第二种形式,客户可以添加他或她选择的产品规格。表单是输入类型文本和文本区域的 然后php询问第二个表单的提交按钮的名称 但问题是当客户端按submit以获取第二个表单时 如果第一个表单未设置,那么其余的代码应该检查第二个表单不存在,因为两个表单都退出代

  • 问题内容: 我有一个模板页面,需要两种形式。如果我仅使用一种形式,则可以像下面的典型示例一样正常: 但是,如果我想使用多个表单,我如何让视图知道我仅提交一种表单,而不提交另一种表单(即,它仍然是request.POST,但我只想处理提交表单的表单)发生了吗? 这是该解决方案基于这样的答案expectedphrase和bannedphrase是的提交按钮的不同形式和名称expectedphrasef