我有一个带有用户名和电子邮件字段的Django表单.我想查看用户尚未使用的电子邮件:
def clean_email(self):
email = self.cleaned_data["email"]
if User.objects.filter(email=email).count() != 0:
raise forms.ValidationError(_("Email not available."))
return email
Run Code Online (Sandbox Code Playgroud)
这有效,但会引发一些漏报,因为电子邮件可能已经存在于表单中指定用户的数据库中.我想改成这个:
def clean_email(self):
email = self.cleaned_data["email"]
username = self.cleaned_data["username"]
if User.objects.filter(email=email, username__ne=username).count() != 0:
raise forms.ValidationError(_("Email not available."))
return email
Run Code Online (Sandbox Code Playgroud)
Django文档说,一个字段的所有验证都是在进入下一个字段之前完成的.如果在用户名之前清除了电子邮件,那么cleaned_data["username"]将无法使用clean_email.但是文档还不清楚字段清理的顺序.我在表单中的电子邮件之前声明用户名,这是否意味着我可以安全地假设用户名在电子邮件之前被清除了?
我可以阅读代码,但我对Django API的承诺更感兴趣,并且知道即使在未来版本的Django中我也很安全.
.keyOrder不再有效.我相信这应该有效:
from collections import OrderedDict
class MyForm(forms.ModelForm):
…
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
field_order = ['has_custom_name', 'name']
reordered_fields = OrderedDict()
for fld in field_order:
reordered_fields[fld] = self.fields[fld]
for fld, value in self.fields.items():
if fld not in reordered_fields:
reordered_fields[fld] = value
self.fields = reordered_fields
Run Code Online (Sandbox Code Playgroud)
无论您如何在表单定义中声明它们,都可以改变表单顺序.其中一个是如果你正在使用a ModelForm,在这种情况下,除非你在fields下面声明了两个字段,否则class Meta它们将处于不可预测的顺序.
幸运的是,有一个可靠的解决方案.
self.fields.keyOrder.以下是您可以使用的示例代码:
class MyForm(forms.ModelForm):
has_custom_name = forms.BooleanField(label="Should it have a custom name?")
name = forms.CharField(required=False, label="Custom name")
class Meta:
model = Widget
fields = ['name', 'description', 'stretchiness', 'egginess']
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
ordered_fields = ['has_custom_name', 'name']
self.fields.keyOrder = ordered_fields + [k for k in self.fields.keys() if k not in ordered_fields]
def clean_name(self):
data = self.cleaned_data
if data.get('has_custom_name') and not data.get('name'):
raise forms.ValidationError("You must enter a custom name.")
return data.get('name')
Run Code Online (Sandbox Code Playgroud)
使用keyOrderset,has_custom_name将在验证self.cleaned_data之前进行验证(因此存在)name.
没有承诺以任何特定顺序处理字段.官方建议,任何依赖于多个字段的验证都应该使用表单的clean()方法,而不是特定于字段的clean_foo()方法.
Django文档声称它是按字段定义的顺序.
但我发现它并不总是能够实现这一承诺.资料来源:http://docs.djangoproject.com/en/dev/ref/forms/validation/
这些方法按上面给出的顺序运行,一次一个字段.也就是说,对于表单中的每个字段(按照它们在表单定义中声明的顺序),运行Field.clean()方法(或其覆盖),然后运行clean_().最后,一旦为每个字段运行这两个方法,就会执行Form.clean()方法或其覆盖.