2010-09-29 20 views
5

Mam formularz dla modelu, który ma dwa pola: field_A i field_B. Chcę:Zmień dane formularza Django przed jego przetworzeniem

  • gdy formularz jest renderowane: wyświetlany jest tylko field_A
  • gdy zgłoszę form.save() field_B zostanie zapisany w modelu o wartości od field_A

Co ja Wcześniej próbowałem:

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) 

* oba pola są dziedziczone od ParentClass, gdzie są one wymagane

+0

dodana informacja edytować – Victor

Odpowiedz

5

Oto rozwiązanie, które działało dla mnie.

# 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 

wyjaśnienie formularza Meta

exclude = ('field_B',) 

zapewnia, że ​​pierwszy warunek jest spełniony. Po wyświetleniu formularza użytkownikowi wyświetlany jest tylko field_A. Drugi warunek jest rozwiązany w nadpisanej metodzie save().

Wyjaśnienie save()

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

Extract argument commit słowa kluczowego, jeśli dostarczone.

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

Utwórz instancję modelu podstawowego. Jawnie przekazać commit=False, aby upewnić się, że ta instancja nie została jeszcze zapisana w bazie danych.

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

Przypisywanie wartości field_A z cleaned_data do instancji field_B. Pamiętaj, że powinieneś wcześniej zadzwonić pod numer form.is_valid(). W przeciwnym razie nie będzie to cleaned_data.

 if commit: 
      instance.save() 

Jeśli użytkownik chce, aby instancja została zapisana w bazie danych, należy to zrobić.

return instance 

Na koniec zwróć instancję.

Wykorzystanie próbki

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

to masywny Hack chociaż ... jaki powinien być właściwy sposób wprowadzania non-user-edycji danych pochodzących z modeli takich jak ModelForm nazwa użytkownika itp? – xster

+0

@Xster: twoją odpowiedzią jest sposób, w jaki robię to dla pól 'user',' modified_by' itp. MOJA odpowiedź spełniła bardzo specyficzne żądanie. Nigdy nie spotkałem się z taką sytuacją w produkcji. –

Powiązane problemy