2010-12-01 19 views
1

J'essaie d'implémenter MultiValueField pour les adresses IP/nom de domaine. Cela fonctionne comme prévu pour la saisie de données. Mon problème est que si je veux afficher le formulaire lié à des données spécifiques, le champ Adresse IP/Nom de domaine reste vide. Tous les autres champs sont remplis avec les données souhaitées. Si j'utilise un CharField normal, j'obtiens les données auxquelles je m'attendrais. Mais cela ne fonctionne pas avec mon champ personnalisé. Je l'ai suivi jusqu'au fait que mon MultiWidget personnalisé n'appelle pas sa méthode de décompression.django sous-classe multiwidget n'appelant pas decompress()

Voici mon champ:

class accessIPField(forms.MultiValueField): 
    """                   
    custom Field for access IP             
    """                   

    def __init__(self, *args, **kwargs):           
     self.fields=(               
      forms.IPAddressField(label='IP Adress'),        
      forms.CharField(max_length=50,label='Domain Name')     
     )                  
     self.widget=accessIPWidget()            
     super(accessIPField,self).__init__(self.fields,self.widget, *args, **kwargs) 

    def compress(self,data_list):            
     if data_list:               
      return " ".join(data_list) 

Et voici mon widget:

class accessIPWidget(forms.MultiWidget): 
    """ 
    Widget to display IP Adress/Domain name pairs 
    """ 
    def __init__(self,*args,**kwargs): 
     self.widgets=(forms.TextInput(),forms.TextInput()) 
     super(accessIPWidget,self).__init__(self.widgets,*args,**kwargs) 

    def decompress(self,value): 
     print 'decompress called' 
     if value: 
      return value.rsplit() 
     return [None,None] 

    def format_output(self, rendered_widgets): 
     return u'\n'.join(rendered_widgets) 

L'ensemble est appelé (dans un contexte plus large) comme

self.fields['access_IPs'] = accessIPField() 

Maintenant que vous pouvez voir, je mets une déclaration d'impression dans ma méthode de compression, et je ne peux jamais voir cette déclaration. De plus, si je renomme compresser en quelque chose comme foobar, je m'attendrais (selon le code django pour MultiWidget) à obtenir l'erreur NotImplementedError, ce qui n'est pas le cas. Aucune suggestion? J'utilise python 2.6.5, django 1.1 sur le serveur ubuntu 10.04.

+0

D'autres semblent avoir aussi ce problème: http://groups.google.com/group/django-users/browse_thread/thread/278e720f8b023877/ec8c2c1822a29d46?lnk=gst&q=decompress#ec8c2c1822a29d46 – Isaac

+0

plus de ce problème: http: //groups.google.com/group/django-users/browse_thread/thread/26bea21d91fb99a7/9a92e921c888a7b4?lnk=gst&q=decompress#9a92e921c888a7b4 – Isaac

Répondre

1

Il s'avère que le problème était avec la méthode value_from_datadict() implémentée par MultiWidget. Tout d'abord, il a déjà renvoyé une liste, c'est pourquoi décompresser() n'a pas été appelé en premier lieu. Deuxièmement, il ramène toujours une liste [None, None], c'est pourquoi la forme liée est restée vide.

je devais mettre en œuvre ma propre (au sein de ma classe de accessIPWidget):

def value_from_datadict(self, data, files, name): 
try: 
    return data.get(name,None).rsplit() 
except AttributeError: 
    return [widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)] 

Maintenant, la dernière ligne est ce que la méthode originale a fait. Afin d'obtenir les données dans le formulaire lié, j'avais besoin d'ajouter data.get (nom, Aucun) .rsplit(). Pour autant que je sache, la méthode value_from_datadict d'origine ne fonctionne que pour les champs non liés. Parce qu'il change le nom du champ d'origine pour nommer + '_% s', ce qui est ce que vous obtenez en appuyant sur le bouton Soumettre. Pour remplir une méthode liée, le datadict doit être interrogé uniquement pour 'nom'. Hm, non pas s'il y a un moyen de contourner cela, mais il me semble que ce comportement devrait au moins être documenté quelque part. Peut-être que j'ai mal compris quelque chose?