2010-09-29 16 views
5

Tengo un formulario para un modelo que tiene dos campos: campo_A y campo_B. Quiero:Cambiar los datos del formulario Django antes de que se procese

  • cuando la forma correcta: sólo se muestra field_A
  • cuando llamo form.save() field_B se guarda en el modelo con el valor de field_A

Lo que 'he intentado:

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) 

* ambos campos se heredan de ParentClass, donde son requeridos

+0

información añade a editar – Victor

Respuesta

5

Aquí hay una solución que funcionó para mí.

# 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 

Explicación de la forma de Meta

exclude = ('field_B',) 

Asegura que se cumple la primera condición. Cuando se muestra el formulario al usuario, solo se muestra field_A. La segunda condición se aborda en el método Oreemplazado.

Explicación de save()

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

Extrae el argumento commit palabra clave si se suministra.

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

Cree una instancia del modelo subyacente. Pase explícitamente commit=False para asegurarse de que esta instancia aún no se haya guardado en la base de datos.

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

asignar el valor de field_A de cleaned_data a la instancia de field_B. Recuerde que debería haber llamado al form.is_valid() antes de esto. De lo contrario, no habrá cleaned_data.

 if commit: 
      instance.save() 

Si el usuario desea que la instancia se guarde en la base de datos, hágalo.

return instance 

Finalmente, regrese la instancia.

Ejemplo de uso

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

esto es un corte masivo, aunque ... lo que debería ser la forma correcta de introducir los datos del modelo de usuario no se puede editar procedentes de un ModelForm como el nombre de usuario, etc.? – xster

+0

@ Xster: su respuesta es la forma en que lo hago para los campos 'user',' modified_by' etc. MI respuesta atendió a una solicitud muy específica del formulario. Nunca me he enfrentado a tal situación en la producción. –

Cuestiones relacionadas