2010-06-24 13 views
7

Sto cercando una versione aggiornata di questi Django SuperForms. Non riesco a farlo funzionare in Django 1.2. In particolare, mi piacerebbe che funzionasse con ModelForms.Composto Django/nidificato/sottomodifiche?

mio caso d'uso è quasi identico al suo; Ho un modello Address che vorrei usare come sottomodulo in vari posti. È un dolore provare e combinare tutto nella funzione di visualizzazione.

+0

Che cosa dovrebbero fare i SuperForm? –

+0

Vuoi fondamentalmente un 'ModelForm' che attraversi chiavi esterne? – sdolan

+0

@sdolan: Qualcosa del genere, sì. Bene, non * solo * attraversare chiavi esterne, perché in tal caso le sottomaschere dovrebbero essere esclusivamente basate sulla forma generata automaticamente prodotta dal modello. Mi piacerebbe poter effettivamente scegliere un altro modulo (o modulo del modello) da incorporare. – mpen

risposta

5

Ho aggiornato superforms.py a lavorare w/1.2, e attaccato al biglietto si è collegato al: http://code.djangoproject.com/attachment/ticket/3706/superform.2.py

C'è un progetto su cui sto lavorando che potrebbero trarre beneficio da questo, così ho pensato che passare il tempo e aiutarti anche tu.

tenere a mente che mi ha regalato questo lavoro w/1.2, e non ho davvero cercare di pulire le parti interne. Ora che ho dei test che dimostrano l'API, posso tornare indietro e ripulirlo più tardi.

se si sta utilizzando con ModelForms e desideri la funzionalità save() si dovrà eseguire l'override del metodo sulla vostra classe SUPERFORM.

Attualmente lo ho localmente nel mio repository "comune" con una copertura del 90% di codice che copre più SubForms, moduli secondari misti & moduli dichiarati e ModelForms. Ho incluso i casi di test qui sotto (attenzione, usa la mia classe TestCaseBase, ma questo dovrebbe darti il ​​senso dell'API). Fammi sapere se hai domande o eventuali aree che ho perso.

from django_common.forms.superform import SuperForm, SubForm 
from django_common.test import TestCaseBase 
from django import forms 

class WhenSuperFormsIsUsedWithOnlySubForms(TestCaseBase): 
    def get_superform_with_forms(self, post_data=None): 
     class AddressForm(forms.Form): 
      street = forms.CharField(max_length=255) 
      city = forms.CharField(max_length=255) 

     class BusinessLocationForm(forms.Form): 
      phone_num = forms.CharField(max_length=255) 

     class TestSuperForm(SuperForm): 
      address = SubForm(AddressForm) 
      business_location = SubForm(BusinessLocationForm) 

     return TestSuperForm(data=post_data) 

    def should_not_be_valid_with_no_data(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_false(tsf.is_valid()) 

    def should_have_two_sub_forms(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_equal(len(tsf.base_subforms), 2) 
     self.assert_equal(len(tsf.forms), 2) 

    def should_display_as_ul(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_equal(tsf.as_ul(), '<li><label for="id_business_location-phone_num">Phone num:</label> <input id="id_business_location-phone_num" type="text" name="business_location-phone_num" maxlength="255" /></li>\n<li><label for="id_address-street">Street:</label> <input id="id_address-street" type="text" name="address-street" maxlength="255" /></li>\n<li><label for="id_address-city">City:</label> <input id="id_address-city" type="text" name="address-city" maxlength="255" /></li>') 

    def should_display_as_table(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_equal(tsf.as_table(), '<tr><th><label for="id_business_location-phone_num">Phone num:</label></th><td><input id="id_business_location-phone_num" type="text" name="business_location-phone_num" maxlength="255" /></td></tr>\n<tr><th><label for="id_address-street">Street:</label></th><td><input id="id_address-street" type="text" name="address-street" maxlength="255" /></td></tr>\n<tr><th><label for="id_address-city">City:</label></th><td><input id="id_address-city" type="text" name="address-city" maxlength="255" /></td></tr>') 

    def should_display_as_p(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_equal(tsf.as_p(), '<p><label for="id_business_location-phone_num">Phone num:</label> <input id="id_business_location-phone_num" type="text" name="business_location-phone_num" maxlength="255" /></p>\n<p><label for="id_address-street">Street:</label> <input id="id_address-street" type="text" name="address-street" maxlength="255" /></p>\n<p><label for="id_address-city">City:</label> <input id="id_address-city" type="text" name="address-city" maxlength="255" /></p>') 

    def should_display_as_table_with_unicode(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_equal(tsf.__unicode__(), tsf.as_table()) 

    def should_be_valid_if_good_data(self): 
     data = { 
      'business_location-phone_num' : '8055551234', 
      'address-street' : '1234 Street Dr.', 
      'address-city' : 'Santa Barbara', 
     } 
     tsf = self.get_superform_with_forms(data) 
     self.assert_true(tsf.is_valid()) 
     self.assert_equal(tsf.cleaned_data['business_location']['phone_num'], 
          '8055551234') 
     self.assert_equal(tsf.cleaned_data['address']['street'], '1234 Street Dr.') 
     self.assert_equal(tsf.cleaned_data['address']['city'], 'Santa Barbara') 

    def should_be_invalid_if_missing_data(self): 
     data = { 
      'business_location-phone_num' : '8055551234', 
      'address-street' : '1234 Street Dr.', 
     } 
     tsf = self.get_superform_with_forms(data) 
     self.assert_false(tsf.is_valid()) 

     self.assert_false(tsf.errors['business_location']) 
     self.assert_true(tsf.errors['address']) 
     self.assert_equal(tsf.errors['address']['city'], ['This field is required.']) 

    def should_be_invalid_if_invalid_data(self): 
     data = { 
      'business_location-phone_num' : '8055551234', 
      'address-street' : '1234 Street Dr.', 
      'address-city' : '', 
     } 
     tsf = self.get_superform_with_forms(data) 
     self.assert_false(tsf.is_valid()) 


class WhenSuperformsIsUsedWithSubFormsAndDeclaredFields(TestCaseBase): 
    """Some basic sanity checks that working with fields combined with SubForms works.""" 
    def get_superform_with_forms(self, post_data=None): 
     class AddressForm(forms.Form): 
      street = forms.CharField(max_length=255) 

     class TestSuperForm(SuperForm): 
      name = forms.CharField(max_length=255) 
      address = SubForm(AddressForm) 

     return TestSuperForm(data=post_data) 

    def should_not_be_valid_with_no_data(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_false(tsf.is_valid()) 

    def should_have_two_forms_and_a_single_subform(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_equal(len(tsf.base_subforms), 1) 
     self.assert_equal(len(tsf.forms), 2) 

    def should_print_as_table(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_equal(tsf.as_table(), '<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="255" /></td></tr>\n<tr><th><label for="id_address-street">Street:</label></th><td><input id="id_address-street" type="text" name="address-street" maxlength="255" /></td></tr>') 

    def should_validate_when_fields_exist(self): 
     data = { 
      'name': 'Sam', 
      'address-street': 'Some Street', 
     } 
     tsf = self.get_superform_with_forms(data) 
     self.assert_true(tsf.is_valid()) 

     self.assert_equal(tsf.cleaned_data['name'], 'Sam') 
     self.assert_equal(tsf.cleaned_data['address']['street'], 'Some Street') 

    def should_not_validate_with_invalid_data(self): 
     data = { 
      'name': '', 
      'address-street': 'Some Street', 
     } 
     tsf = self.get_superform_with_forms(data) 
     self.assert_false(tsf.is_valid()) 

     self.assert_equal(tsf.errors['name'], ['This field is required.']) 



class WhenSuperformsIsUsedWithModelForms(TestCaseBase): 
    def get_superform_with_forms(self, post_data=None): 
     from django.db import models 
     class Address(models.Model): 
      city = models.CharField(max_length=255) 

     class AddressForm(forms.ModelForm): 
      class Meta: 
       model = Address 

     class TestSuperForm(SuperForm): 
      address = SubForm(AddressForm) 

     return TestSuperForm(data=post_data) 

    def should_not_be_valid_with_no_data(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_false(tsf.is_valid()) 

    def should_have_two_forms_and_a_single_subform(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_equal(len(tsf.base_subforms), 1) 
     self.assert_equal(len(tsf.forms), 1) 

    def should_print_as_table(self): 
     tsf = self.get_superform_with_forms() 
     self.assert_equal(tsf.as_table(), '<tr><th><label for="id_address-city">City:</label></th><td><input id="id_address-city" type="text" name="address-city" maxlength="255" /></td></tr>') 

    def should_validate_when_fields_exist(self): 
     data = { 
      'address-city': 'Some City', 
     } 
     tsf = self.get_superform_with_forms(data) 
     self.assert_true(tsf.is_valid()) 

     self.assert_equal(tsf.cleaned_data['address']['city'], 'Some City') 

    def should_not_validate_with_invalid_data(self): 
     data = { 
      'address-city': '', 
     } 
     tsf = self.get_superform_with_forms(data) 
     self.assert_false(tsf.is_valid()) 

     self.assert_equal(tsf.errors['address']['city'], ['This field is required.']) 

Divertiti!

+0

Wow, è fantastico! Grazie mille :) Purtroppo questo è arrivato un po 'in ritardo per il mio progetto attuale (ho trovato un altro sol'n), ma forse per il mio prossimo! – mpen

+0

Sì, nessun problema. Grazie per aver posto la domanda e aver dato un buon punto di partenza. Questo è qualcosa che mi sarebbe stato utile per molto tempo. Per quanto riguarda la tua altra soluzione, cosa hai fatto? Oh, e ho guadagnato la taglia? :) – sdolan

+0

Sei sicuro di sì. Sto assumendo che il tuo codice funzioni effettivamente;) Cosa ho finito per fare? Solo la cosa più stupida che un programmatore possa fare! Ha riscritto l'* intero * form app da zero! – mpen

Problemi correlati