6

我想創建爲(分別爲大小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) 
+0

你不只是使用我們的任何原因。 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

+0

這將是有益的知道回溯正在發生 - 即提供更多的細節遠遠不止這些一條線。 – 2009-11-22 08:28:27

+0

在參考了@hughdbrown Django的Localflavor提出的建議是在Django 1.5現在所在搬出在https://github.com/django/django-localflavor – davelupt 2015-08-31 18:18:56

回答

1

我拿了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']) 
5

它使用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()) 
0

有時是修復原來的問題,而不是重做一切有用。你得到的錯誤,「在呈現時捕獲到一個異常:'NoneType'對象是無法訪問的」有一條線索。當預計可付款的價值時,返回的值爲無(不可訂閱)。 PhoneNumberWidget類中的解壓縮函數是一個可能的罪魁禍首。我會建議返回[]而不是無。

3

我認爲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)] 
+0

這個工作得很好,但我在得到一個錯誤在Django 1.3 value_from_datadict函數,因爲values變量不是元組而是列表。我不得不使用元組(值)轉換列表,使其正常工作。我相應地編輯了答案。 – bchhun 2011-06-15 14:55:54