在 clean() 期间修改 Django 表单字段的值并再次验证
Modify value of a Django form field during clean() and validate again
我想做这样的事情:
class UsuarioForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UsuarioForm, self).__init__(*args, **kwargs)
self.fields['cpf'].widget.attrs['maxlength'] = 14
self.fields['telefone'].widget.attrs['maxlength'] = 15
self.fields['celular'].widget.attrs['maxlength'] = 15
nome = forms.CharField(widget=forms.TextInput(attrs={'readonly': True,
'icone': 'fa fa-font'}))
usuario = forms.CharField(widget=forms.TextInput(attrs={'readonly': True,
'icone': 'fa fa-user'}))
def clean(self):
cleaned_data = self.cleaned_data
self.data['cpf'] = re.sub("[\.-]", "", self.data['cpf'])
clean_data_again_to_revalidate_the_field
class Meta:
model = Usuario
exclude = ['codigo', 'estabelecimento', 'dono', 'data', 'estabelecimento', 'cargo', 'usuario']
widgets = {
'cpf': forms.TextInput(attrs={'placeholder': Text().cpf(),
'icone': 'fa fa-credit-card',
'id':'cpf',
}),
'telefone': forms.TextInput(attrs={'placeholder': Text().telefone(),
'icone': 'fa fa-phone'.decode('utf-8'),
'id': Text().telefone()}),
'celular': forms.TextInput(attrs={'placeholder': Text().celular(),
'icone': 'fa fa-mobile',
'id': Text().celular()}),
}
我想更改字段 CPF 以删除点。之后,我想再次验证该字段。可能吗?
另外,self.data['cpf'] 接收值是不可能的。它失败了:This QueryDict instance is immutable.
我创建了方法 clean_cpf,但它从未被调用过。我认为是因为 cpf 字段没有出现在 cleaned_data 中,因为在我接收数据的格式中是无效的。
此外,cpf 不在 cleaned_data 中。我认为是因为无效。 cpf 的最大长度为 11,但是当它来自屏幕时,该字段有 14 个字符。这就是为什么我需要更改字段并再次验证它的原因。
Q&D hack 将直接在表单的 __init__
中修复 data
中的值(注意:未经测试的代码):
class UsuarioForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UsuarioForm, self).__init__(*args, **kwargs)
if self.data:
# make the QueryDict mutable
self.data = self.data.copy()
# remove dots from data["cpf"]
if "cpf" in self.data:
self.data["cpf"] = self.data["cpf"].replace(".", "")
# ...
但是,如果您仍然遇到验证错误,则在重新显示表单时,"cpf" 字段的数据将呈现为不带点的渲染器。
更简洁的解决方案是使用自定义 "CreditCard" 字段,因为您的 cpf 字段似乎需要信用卡号。网络上有几个第三方实现,可以开箱即用或至少提供一个起点。
附带说明:您在表单 Meta
中覆盖默认小部件,然后在表单 __init__
中覆盖相同字段的 "max_length",这不是很干。您应该直接在 Meta.widgets
部分设置最大长度。
我想做这样的事情:
class UsuarioForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UsuarioForm, self).__init__(*args, **kwargs)
self.fields['cpf'].widget.attrs['maxlength'] = 14
self.fields['telefone'].widget.attrs['maxlength'] = 15
self.fields['celular'].widget.attrs['maxlength'] = 15
nome = forms.CharField(widget=forms.TextInput(attrs={'readonly': True,
'icone': 'fa fa-font'}))
usuario = forms.CharField(widget=forms.TextInput(attrs={'readonly': True,
'icone': 'fa fa-user'}))
def clean(self):
cleaned_data = self.cleaned_data
self.data['cpf'] = re.sub("[\.-]", "", self.data['cpf'])
clean_data_again_to_revalidate_the_field
class Meta:
model = Usuario
exclude = ['codigo', 'estabelecimento', 'dono', 'data', 'estabelecimento', 'cargo', 'usuario']
widgets = {
'cpf': forms.TextInput(attrs={'placeholder': Text().cpf(),
'icone': 'fa fa-credit-card',
'id':'cpf',
}),
'telefone': forms.TextInput(attrs={'placeholder': Text().telefone(),
'icone': 'fa fa-phone'.decode('utf-8'),
'id': Text().telefone()}),
'celular': forms.TextInput(attrs={'placeholder': Text().celular(),
'icone': 'fa fa-mobile',
'id': Text().celular()}),
}
我想更改字段 CPF 以删除点。之后,我想再次验证该字段。可能吗?
另外,self.data['cpf'] 接收值是不可能的。它失败了:This QueryDict instance is immutable.
我创建了方法 clean_cpf,但它从未被调用过。我认为是因为 cpf 字段没有出现在 cleaned_data 中,因为在我接收数据的格式中是无效的。
此外,cpf 不在 cleaned_data 中。我认为是因为无效。 cpf 的最大长度为 11,但是当它来自屏幕时,该字段有 14 个字符。这就是为什么我需要更改字段并再次验证它的原因。
Q&D hack 将直接在表单的 __init__
中修复 data
中的值(注意:未经测试的代码):
class UsuarioForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UsuarioForm, self).__init__(*args, **kwargs)
if self.data:
# make the QueryDict mutable
self.data = self.data.copy()
# remove dots from data["cpf"]
if "cpf" in self.data:
self.data["cpf"] = self.data["cpf"].replace(".", "")
# ...
但是,如果您仍然遇到验证错误,则在重新显示表单时,"cpf" 字段的数据将呈现为不带点的渲染器。
更简洁的解决方案是使用自定义 "CreditCard" 字段,因为您的 cpf 字段似乎需要信用卡号。网络上有几个第三方实现,可以开箱即用或至少提供一个起点。
附带说明:您在表单 Meta
中覆盖默认小部件,然后在表单 __init__
中覆盖相同字段的 "max_length",这不是很干。您应该直接在 Meta.widgets
部分设置最大长度。