Django的MultiWidget电话号码字段
我想创建为(分别为大小3,3和4)具有2个文本字段的电话号码输入与普通场“(”“)”“ - ”分隔符。下面是我的代码字段和小部件,当我尝试迭代我的表单中的字段在初始呈现期间(它发生在for循环到达我的电话号码字段时)时出现以下错误:Django的MultiWidget电话号码字段
Caught而渲染的异常:“NoneType”对象是unsubscriptable
class PhoneNumberWidget(forms.MultiWidget):
def __init__(self,attrs=None):
wigs = (forms.TextInput(attrs={'size':'3','maxlength':'3'}),\
forms.TextInput(attrs={'size':'3','maxlength':'3'}),\
forms.TextInput(attrs={'size':'4','maxlength':'4'}))
super(PhoneNumberWidget, self).__init__(wigs, attrs)
def decompress(self, value):
return value or None
def format_output(self, rendered_widgets):
return '('+rendered_widgets[0]+')'+rendered_widgets[1]+'-'+rendered_widgets[2]
class PhoneNumberField(forms.MultiValueField):
widget = PhoneNumberWidget
def __init__(self, *args, **kwargs):
fields=(forms.CharField(max_length=3), forms.CharField(max_length=3), forms.CharField(max_length=4))
super(PhoneNumberField, self).__init__(fields, *args, **kwargs)
def compress(self, data_list):
if data_list[0] in fields.EMPTY_VALUES or data_list[1] in fields.EMPTY_VALUES or data_list[2] in fields.EMPTY_VALUES:
raise fields.ValidateError(u'Enter valid phone number')
return data_list[0]+data_list[1]+data_list[2]
class AdvertiserSumbissionForm(ModelForm):
business_phone_number = PhoneNumberField(required=True)
我拿了hughdbrown的建议和修改USPhoneNumberField做什么,我需要。我最初没有使用它的原因是它将数据库中的电话号码存储为XXX-XXX-XXXX,我将它们存储为XXXXXXXXXX。所以我过骑着清洁方法:
class PhoneNumberField(USPhoneNumberField):
def clean(self, value):
super(USPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return u''
value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))
m = phone_digits_re.search(value)
if m:
return u'%s%s%s' % (m.group(1), m.group(2), m.group(3))
raise ValidationError(self.error_messages['invalid'])
它使用widget.value_from_datadict()
格式化数据所以没有需要继承的字段,只需使用现有的USPhoneNumberField
。数据存储在数据库中,如XXX-XXX-XXXX。在形式
from django import forms
class USPhoneNumberMultiWidget(forms.MultiWidget):
"""
A Widget that splits US Phone number input into three <input type='text'> boxes.
"""
def __init__(self,attrs=None):
widgets = (
forms.TextInput(attrs={'size':'3','maxlength':'3', 'class':'phone'}),
forms.TextInput(attrs={'size':'3','maxlength':'3', 'class':'phone'}),
forms.TextInput(attrs={'size':'4','maxlength':'4', 'class':'phone'}),
)
super(USPhoneNumberMultiWidget, self).__init__(widgets, attrs)
def decompress(self, value):
if value:
return value.split('-')
return (None,None,None)
def value_from_datadict(self, data, files, name):
value = [u'',u'',u'']
# look for keys like name_1, get the index from the end
# and make a new list for the string replacement values
for d in filter(lambda x: x.startswith(name), data):
index = int(d[len(name)+1:])
value[index] = data[d]
if value[0] == value[1] == value[2] == u'':
return None
return u'%s-%s-%s' % tuple(value)
使用像这样:
from django.contrib.localflavor.us.forms import USPhoneNumberField
class MyForm(forms.Form):
phone = USPhoneNumberField(label="Phone", widget=USPhoneNumberMultiWidget())
有时是修复原来的问题,而不是重做一切有用。你得到的错误,“在呈现时捕获到一个异常:'NoneType'对象是无法访问的”有一条线索。当预计可付款的价值时,返回的值为无(不可订阅)。 PhoneNumberWidget类中的解压缩函数是一个可能的罪魁祸首。我会建议返回[]而不是无。
我认为value_from_datadict()的代码可以简化为:
class USPhoneNumberMultiWidget(forms.MultiWidget):
"""
A Widget that splits US Phone number input into three boxes.
"""
def __init__(self,attrs=None):
widgets = (
forms.TextInput(attrs={'size':'3','maxlength':'3', 'class':'phone'}),
forms.TextInput(attrs={'size':'3','maxlength':'3', 'class':'phone'}),
forms.TextInput(attrs={'size':'4','maxlength':'4', 'class':'phone'}),
)
super(USPhoneNumberMultiWidget, self).__init__(widgets, attrs)
def decompress(self, value):
if value:
return value.split('-')
return [None,None,None]
def value_from_datadict(self, data, files, name):
values = super(USPhoneNumberMultiWidget, self).value_from_datadict(data, files, name)
return u'%s-%s-%s' % values
为MultiValueWidget的value_from_datadict()方法已经执行以下操作:
def value_from_datadict(self, data, files, name):
return [widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
这个工作得很好,但我在得到一个错误在Django 1.3 value_from_datadict函数,因为values变量不是元组而是列表。我不得不使用元组(值)转换列表,使其正常工作。我相应地编辑了答案。 – bchhun 2011-06-15 14:55:54
你不只是使用我们的任何原因。 PhoneNumberField和us.forms.USPhoneNumberField?非常方便,如果你有美国的ophone号码。 http://docs.djangoproject.com/en/dev/ref/contrib/localflavor/#united-states-of-america-us – hughdbrown 2009-11-22 02:01:42
这将是有益的知道回溯正在发生 - 即提供更多的细节远远不止这些一条线。 – 2009-11-22 08:28:27
在参考了@hughdbrown Django的Localflavor提出的建议是在Django 1.5现在所在搬出在https://github.com/django/django-localflavor – davelupt 2015-08-31 18:18:56