我有一些带有某些字段的模型。
我有一个模型表单,代表上述模型的一部分。我必须做一些自定义验证。有些领域依赖于其他领域。例如,密码和密码确认字段必须相同。它与后端系统联系在一起。
我必须检查登录名(确保它不在后端系统中,而不是在该项目的数据库中)。我必须验证长度等等。
然后我必须根据后端设置的约束来验证密码。我需要为此使用API。我必须使用密码传递登录名以使用此命令(它很傻但我不能改变它。)
如果登录名在其方法中引发验证错误,则密码验证methid不能使用sel.cleaned_data ['login']
这是代码。
class PEMUserDetails(models.Model):
#Keys and IDs
domain = models.OneToOneField('GIBOSite', primary_key=True)
domain_name = models.CharField(unique=True, max_length=100)
# Details
PEM_login_id = models.CharField(max_length=32, unique=True)
PEM_password = models.CharField(max_length=32)
PEM_password_confirm = models.CharField(max_length=32)
FTP_login = models.CharField(max_length=32, blank=True, null=True)
FTP_password = models.CharField(max_length=32, blank=True, null=True)
FTP_host_name = models.CharField(max_length=256, blank=True, null=True)
def __unicode__(self):
return self.domain_name
def link_to(self, gibo_site):
self.domain = gibo_site
self.domain_name = gibo_site.domain
class PEMUserDetailsForm(forms.ModelForm):
PEM_password = forms.CharField(widget=forms.PasswordInput)
PEM_password_confirm = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = PEMUserDetails
exclude = ('domain', 'domain_name', 'FTP_login', 'FTP_password', 'FTP_host_name')
def clean_PEM_login_id(self):
login = self.cleaned_data['PEM_login_id']
try:
g = PEMUserDetails.objects.get(PEM_login_id=login)
raise forms.ValidationError("This Login ID is already taken, please choose another.")
except PEMUserDetails.DoesNotExist:
p = PBA()
pem_account = p.BM.UserValidate_API(login)
if pem_account['AccountID'] == 0:
pass
else:
raise forms.ValidationError("This Login ID is already taken, please choose another.")
validation = p.BM.GetLoginSettings_API()
m = re.match(validation['ManualLoginMask'], login)
if m == None:
raise forms.ValidationError(validation['LoginAlert'])
valid_login = (login == m.group(0))
if len(login) > validation['LoginMinLength'] and len(login) < validation['LoginMaxLength'] and valid_login:
pass
else:
raise forms.ValidationError(validation['LoginAlert'])
return login
def clean_PEM_password(self):
p = PBA()
login = self.cleaned_data['PEM_login_id']
password = self.cleaned_data['PEM_password']
validation = p.BM.GetLoginSettings_API()
if len(password) > validation['PwdMinLength']:
pass
else:
raise forms.ValidationError("Password must be more than %s characters long" % validation['PwdMinLength'])
passwd_status = p.BM.UserForVendorValidate_API(login, password)
if passwd_status['passwordStrength'] == '':
pass
else:
raise forms.ValidationError(passwd_status['passwordStrength'])
return password
def clean_PEM_password_confirm(self):
p = self.cleaned_data['PEM_password']
c = self.cleaned_data['PEM_password_confirm']
if c == p:
pass
else:
raise forms.ValidationError("The passwords you submitted do not match")
return c
我通过使用常规表单并将其与模型类匹配来解决这个问题。它摆脱了这个问题。这是django 1.1中模型形式的限制吗?
python shell显示了这个
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from gibo.deployment.models import PEMUserDetailsForm
>>> from django.http import QueryDict
>>> post = QueryDict("PEM_login_id=beefsupreme&PEM_password=beef1234&PEM_password_confirm=beef123")
>>> f = PEMUserDetailsForm(post)
>>> f.is_valid()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/lib/pymodules/python2.6/django/forms/forms.py", line 120, in is_valid
return self.is_bound and not bool(self.errors)
File "/usr/lib/pymodules/python2.6/django/forms/forms.py", line 111, in _get_errors
self.full_clean()
File "/usr/lib/pymodules/python2.6/django/forms/forms.py", line 243, in full_clean
value = getattr(self, 'clean_%s' % name)()
File "/home/niall/public_html/projects/GIBO/dev/projects/signup/gibo/../gibo/deployment/models.py", line 776, in clean_PEM_password
login = self.cleaned_data['PEM_login_id']
KeyError: 'PEM_login_id'
>>> post = QueryDict("PEM_login_id=beefsupremexxc&PEM_password=beef1234&PEM_password_confirm=beef123")
>>> f = PEMUserDetailsForm(post)
>>> f.is_valid()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/lib/pymodules/python2.6/django/forms/forms.py", line 120, in is_valid
return self.is_bound and not bool(self.errors)
File "/usr/lib/pymodules/python2.6/django/forms/forms.py", line 111, in _get_errors
self.full_clean()
File "/usr/lib/pymodules/python2.6/django/forms/forms.py", line 243, in full_clean
value = getattr(self, 'clean_%s' % name)()
File "/home/niall/public_html/projects/GIBO/dev/projects/signup/gibo/../gibo/deployment/models.py", line 791, in clean_PEM_password_confirm
p = self.cleaned_data['PEM_password']
KeyError: 'PEM_password'
>>> f.errors
{'PEM_password': [u'Password is based on personal information.']}
>>>
但它的工作原理
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from gibo.deployment.models import PEMUserDetailsForm
>>> from django.http import QueryDict
>>> post = QueryDict("PEM_login_id=beefsupreme&PEM_password=beef1234&PEM_password_confirm=beef123")
>>> f = PEMUserDetailsForm(post)
>>> f.errors
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/lib/pymodules/python2.6/django/forms/forms.py", line 111, in _get_errors
self.full_clean()
File "/usr/lib/pymodules/python2.6/django/forms/forms.py", line 243, in full_clean
value = getattr(self, 'clean_%s' % name)()
File "/home/niall/public_html/projects/GIBO/dev/projects/signup/gibo/../gibo/deployment/models.py", line 777, in clean_PEM_password
login = self.cleaned_data['PEM_login_id']
KeyError: 'PEM_login_id'
>>> f.errors
{'PEM_login_id': [u'This Login ID is already taken, please choose another.']}
>>> f.is_valid()
False
>>>
答案 0 :(得分:3)
特定于字段的清理方法 - clean_PEM_password()等 - 应该只从self.cleaned_data访问该特定字段。其他字段无法保证尚未设置。如果需要针对多个字段进行验证,则应使用clean()方法,因为已经运行了所有特定于字段的验证方法。
答案 1 :(得分:0)
在执行字段验证功能时,您无法访问“cleaning_data”,因为只有在所有字段都通过验证后才能访问cleaning_data。
因此,您要么找到一种没有“cleaning_data”的工作方式,要么定义一个clean()方法,您可以在其中访问“cleaning_data”,然后编写自定义验证逻辑并在需要时抛出ValidationErrors。
我倾向于在我自己的项目中使用选项b,除非我真的创建了一种新类型的表单域,其中需要进行自定义验证 - 尤其是在检查数据库中是否存在数据时。