2010-09-29 9 views
5

J'ai un formulaire pour un modèle avec deux champs: field_A et field_B. Je veux:Modifier les données de formulaire Django avant qu'elles ne soient traitées

  • lorsque le formulaire est rendu: que Champ_A est affiché
  • quand j'appelle form.save() Champ_B est enregistré dans le modèle avec la valeur de Champ_A

Ce que je « ai essayé:

field_A = forms.CharField(required=True) 
field_B = forms.CharField(required=False) 

def save(self, *args, **kwargs): 
    """ 
    Overriding save, so call the parent form save and return the new_user 
    object. 
    """ 
    self.data["field_B"] = self.data["field_A"] 
    self.cleaned_data["username"] = self.cleaned_data["email"] 
    super(MyParentClass*, self).save(*args, **kwargs) 

* les deux champs sont hérités de ParentClass, où ils sont nécessaires

+0

ajouté informations pour modifier – Victor

Répondre

5

Voici une solution qui a fonctionné pour moi.

# models.py 
class MyModel(models.Model): 
    field_A = models.CharField(max_length = 255) 
    field_B = models.CharField(max_length = 255) 

    def __unicode__(self): 
     return "%s: %s, %s" % (self.pk, self.field_A, self.field_B) 

# forms.py 
class MyModelForm(ModelForm): 
    class Meta: 
     model = MyModel 
     exclude = ('field_B',) 

    def save(self, *args, **kwargs): 
     commit = kwargs.pop('commit', True) 
     instance = super(MyModelForm, self).save(*args, commit = False, **kwargs) 
     instance.field_B = self.cleaned_data['field_A'] 
     if commit: 
      instance.save() 
     return instance 

Explication des Meta

exclude = ('field_B',) 

assure que votre première condition de la forme est remplie. Lorsque le formulaire est affiché à l'utilisateur, seul le message field_A est affiché. La deuxième condition est traitée dans la méthode save() remplacée.

Explication des save()

commit = kwargs.pop('commit', True) 

Extrait l'argument mot-clé commit si fourni.

instance = super(MyModelForm, self).save(*args, commit = False, **kwargs) 

Créez une instance du modèle sous-jacent. Passez explicitement commit=False pour vous assurer que cette instance n'est pas encore enregistrée dans la base de données.

instance.field_B = self.cleaned_data['field_A'] 

affecter la valeur de field_Acleaned_data-field_B de l'instance. Rappelez-vous que vous devriez avoir appelé form.is_valid() avant cela. Sinon, il n'y aura pas de cleaned_data. Si l'utilisateur souhaite que l'instance soit enregistrée dans la base de données, faites-le.

return instance 

Enfin, renvoyez l'instance.

Exemple d'utilisation

In [1]: from app.forms import MyModelForm 

In [2]: f = MyModelForm(data = {'field_A': 'Value A'}) 

In [3]: f.is_valid() 
Out[3]: True 

In [4]: f.save() 
Out[4]: <MyModel: 3: Value A, Value A> 

In [5]: f = MyModelForm(data = {'field_A': 'VA'}) 

In [6]: f.is_valid() 
Out[6]: True 

In [7]: f.save(commit = False) 
Out[7]: <MyModel: None: VA, VA> 

In [8]: 
+0

c'est un hack massif mais ... ce qui devrait être la bonne façon de saisir des données de modèle non modifiables par l'utilisateur provenant d'un ModelForm comme le nom d'utilisateur etc? – xster

+0

@Xster: votre réponse est la façon dont je le fais pour les champs 'user',' modified_by' etc. Ma réponse répondait à une demande très spécifique à un formulaire. Je n'ai jamais fait face à une telle situation dans la production. –