我的Django模型字段有什么问题?
我正在尝试创建一个电话字段,这个字段可以把输入的值转换成标准格式。
在这种情况下,我想使用这个清理方法。
def clean(self):
phone = self.cleaned_data.get('phone')
# Is it already standardized ?
if phone.startswith('+'):
mo = re.search(r'^\+\d{2,3}\.\d{9,11}$', phone)
if not mo:
raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
else:
return phone
# If not, it must be a french number.
phone = re.sub("\D", "", phone) # Suppression des caractères séparateurs
mo = re.search(r'^\d{10}$', phone) # Numéro à 10 chiffres
if not mo:
raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
else:
phone = mo.group()[-9:]
return u'+33.%s' % phone
如果我把它放在一个表单里,它工作得很好。
但是我想把它当作一个表单字段来使用。
我试着这样做:
EMPTY_VALUES = (None, '')
class PhoneInput (forms.TextInput):
def render(self, name, value, attrs=None):
if value not in EMPTY_VALUES:
value = phone_render(value)
else:
value = None
return super(PhoneInput, self).render(name, value, attrs)
class PhoneField(models.CharField):
widget = PhoneInput
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 16
super(PhoneField, self).__init__(*args, **kwargs)
def get_internal_type(self):
return "CharField"
def clean(self, value):
phone = super(PhoneField, self).clean(value)
# Le numéro contient-il un indicatif ?
if phone.startswith('+'):
mo = re.search(r'^\+\d{2,3}\.\d{9,11}$', phone)
if not mo:
raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
else:
return phone
# Pas d'indicatif : on est en France par défaut
phone = re.sub("\D", "", phone) # Suppression des caractères séparateurs
mo = re.search(r'^\d{10}$', phone) # Numéro à 10 chiffres
if not mo:
raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
else:
phone = mo.group()[-9:]
return u'+33.%s' % phone
但是这个清理方法从来没有被调用。你能帮我吗?
2 个回答
1
这是我如何在becomingGuru的帮助下解决这个问题的 :)
class PhoneFormField(forms.CharField):
widget = PhoneInput
def clean(self, value):
phone = super(PhoneFormField, self).clean(value)
# Le numéro contient-il un indicatif ?
if phone.startswith('+'):
mo = re.search(r'^\+\d{2,3}\.\d{9,11}$', phone)
if not mo:
raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
else:
return phone
# Pas d'indicatif : on est en France par défaut
phone = re.sub("\D", "", phone) # Suppression des caractères séparateurs
mo = re.search(r'^\d{10}$', phone) # Numéro à 10 chiffres
if not mo:
raise forms.ValidationError(_(u'Vous devez entrer un numéro de téléphone. (+33.389520638 ou 0389520638).'))
else:
phone = mo.group()[-9:]
return u'+33.%s' % phone
class PhoneField(models.CharField):
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 16
super(PhoneField, self).__init__(*args, **kwargs)
def get_internal_type(self):
return "CharField"
def formfield(self, form_class=PhoneFormField, **kwargs):
return super(PhoneField, self).formfield(form_class=form_class, **kwargs)
谢谢你的帮助。
6
你把模型字段和表单字段搞混了。
首先需要定义表单字段,然后再让相应的模型字段使用这些表单字段来创建模型表单。
可以参考这个文档:指定模型字段的表单字段
基本上,你需要在模型字段上定义一个叫做 formfield 的方法。
def formfield(self, **kwargs):
# This is a fairly standard way to set up some defaults
# while letting the caller override them.
defaults = {'form_class': MyFormField}
defaults.update(kwargs)
return super(HandField, self).formfield(**defaults)
你上面创建的字段有一个 clean 方法,这是表单字段的要求,而不是 模型字段 的要求。
所以,现在你应该定义一个表单字段(就是你之前定义的那个,不过要从 forms.CharField
继承,而不是 models.CharField
),然后按照模型字段的创建规则定义一个模型字段,并包含上面提到的方法。
另外,简单来说,你也可以选择只定义一个表单字段,然后在模型表单中覆盖这个特定模型字段的默认表单字段。(不过在这种情况下,除非从那个模型表单输入数据,否则不会进行验证)