Django 保存表单未完成进度
我有一个用Django做的网页应用,很多用户可以登录并填写表单。
有些用户在填写表单的时候,可能会缺少一些必要的信息(比如说,申请号),这些信息是验证表单所需要的(在我们开始处理之前)。我希望他们可以填写表单,并且有一个选项可以保存部分信息(这样他们可以在其他时间重新登录来完成表单),或者提交完整的信息进行验证。
目前我使用ModelForm来处理所有的表单,而模型中有一些限制来确保数据的有效性(比如,申请号必须是唯一的)。但是,我希望他们能够保存这些中间数据,而不需要进行任何验证。
我想到的解决方案似乎有点笨拙,也不太符合Django的风格:创建一个“保存部分表单”的按钮,保存POST字典并将其转换为一个shelf文件,同时创建一个“SavedPartialForm”模型,将用户和保存在shelf中的部分表单连接起来。这样做合理吗?有没有更好的方法可以直接把POST字典保存到数据库中?或者有没有什么附加模块可以实现表单的部分保存(这在网页表单中似乎是个比较常见的需求)?
我最担心的是,我希望最终能够实现自动保存表单的功能(比如每10分钟自动保存一次),用某种ajax/jquery的方法,而不需要实际按按钮发送POST请求(例如,这样用户在自动保存时不会被重定向到其他页面)。我对jquery不太熟悉,想知道这样做是否可行。
3 个回答
把下面的内容放到你的表单的 __init__
方法里
for field in form.fields:
form.fields[field].required = False
举个例子:
class MySexyForm(Form):
def __init__(self, *args, **kwargs):
super(MySexyForm, self).__init__(*args, **kwargs)
for field in self.fields:
self.fields[field].required = False
然后调用:
form = MySexyForm(...)
form.save()
不过,你需要确保你的 clean()
方法能够处理缺失的属性,方法是检查这些属性是否存在于 cleaned_data 中。比如说,如果另一个表单字段的验证依赖于 customer_id
,但你的表单没有指定这个值,那么 customer_id
就不会出现在 cleaned_data 里。
如果这是一个模型表单,你可以检查这个值是否在 cleaned_data
中,如果缺失了,就可以使用 instance.field
作为备用,比如:
def clean(self):
inst = self.instance
customer_id_new = self.cleaned_data.get('customer_id', None)
customer_id_old = getattr(self.instance, 'customer_id') if inst else None
customer_id = customer_id_new if customer_id_new else customer_id_old
记住,新值的格式几乎肯定和旧值不一样,比如 customer_id
在模型实例中可能是一个 RelatedField
,但在表单数据中却是一个主键 int
。所以,你需要在 clean 方法里处理这些类型的差异。
可惜的是,这正是 Django 表单的一个不足之处。
问题在于你有多个表单。
有部分的、不完整的、完整的,还有准备好的和待处理的。
实际上,你是为工作流程的每个阶段准备了一个表单。
这样做没有任何问题。
先弄清楚你在工作流程的哪个阶段。
填写并展示下一个阶段的表单。
表单之间可以相互继承,这样就可以避免重复验证的方法。
在保存之前:
for field in form.fields:
form.fields[field].required = False
然后:
form.save()