6

Desidero creare un campo per l'immissione del numero di telefono che ha 2 campi di testo (dimensioni 3, 3 e 4 rispettivamente) con i delimitatori comuni "(" ")" "-". Di seguito è il mio codice per il campo e il widget, sto ricevendo il seguente errore quando si tenta di iterare i campi nel mio modulo durante il rendering iniziale (accade quando il ciclo for arriva al mio campo numero di telefono):Campo numero di telefono Django MultiWidget

Catturato un'eccezione durante il rendering: oggetto '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

Qual è il motivo che non sono solo di noi utilizza. models.PhoneNumberField e us.forms.USPhoneNumberField? Molto comodo se si hanno numeri di telefono negli Stati Uniti. http://docs.djangoproject.com/en/dev/ref/contrib/localflavor/#united-states-of-america-us – hughdbrown

+0

Sarebbe utile sapere dove si stava verificando il traceback - cioè dare più dettagli di quello una linea. –

+0

In riferimento al suggerimento fatto da @hughdbrown Django-Localflavor è stato spostato in Django 1.5 ora risiede su https://github.com/django/django-localflavor – davelupt

risposta

1

ho preso di hughdbrown consulenza e modificato USPhoneNumberField di fare quello che mi serve. Il motivo per cui non l'ho usato inizialmente era che memorizza i numeri di telefono come XXX-XXX-XXXX nel DB, li memorizzo come XXXXXXXXXX. Così ho over-guidato il metodo pulito:

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

Questo utilizza widget.value_from_datadict() per formattare i dati in modo non c'è bisogno di creare una sottoclasse un campo, basta usare l'esistente USPhoneNumberField. I dati sono archiviati in db come 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) 

uso in forma in questo modo:

from django.contrib.localflavor.us.forms import USPhoneNumberField 
class MyForm(forms.Form): 
    phone = USPhoneNumberField(label="Phone", widget=USPhoneNumberMultiWidget()) 
0

A volte è utile per risolvere il problema originale, piuttosto che rifare tutto. L'errore che hai ottenuto "Catturato un'eccezione durante il rendering: l'oggetto 'NoneType' è unsubscriptable" ha un indizio. Esiste un valore restituito come None (non sottoscrivibile) quando è previsto un valore subscriptable. La funzione di decompressione nella classe PhoneNumberWidget è un probabile colpevole. Suggerirei di ritornare [] invece di None.

3

penso che il codice value_from_datadict() può essere semplificata:


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 

Il metodo value_from_datadict() per MultiValueWidget fa già il seguente:


    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

questo funziona bene ma ho un errore in Django 1.3 nel funzione value_from_datadict perché la variabile values ​​non è una tupla ma una lista. Ho dovuto convertire la lista usando tuple (valori) per farlo funzionare correttamente. Ho modificato la risposta di conseguenza. – bchhun

Problemi correlati