2010-06-24 8 views
7

Estoy buscando una versión actualizada de estos Django SuperForms. Parece que no funciona en Django 1.2. En particular, me gustaría que funcione con ModelForms.Django compuesto/anidado/subformas?

Mi caso de uso es casi idéntico al suyo; Tengo un modelo Address que me gustaría usar como subformulario en varios lugares. Es un dolor tratar de combinar todo en la vista func.

+0

¿Qué se supone que debe hacer SuperForms? –

+0

¿Básicamente quieres un 'ModeloFormato' que atraviese claves externas? – sdolan

+0

@sdolan: Algo así, sí. Bueno, no * solo * atraviesa claves foráneas, porque entonces los subformularios tendrían que basarse únicamente en el formulario generado automáticamente a partir del modelo. Me gustaría poder elegir otro formulario (o modelo) para insertar. – mpen

Respuesta

5

He actualizado superforms.py trabajar w/1.2, y unido a la entrada se conectó a: http://code.djangoproject.com/attachment/ticket/3706/superform.2.py

Hay un proyecto que estoy trabajando en que podrían beneficiarse de este, así que pensé Pasaría el tiempo y te ayudaría también.

Tenga en cuenta que acabo de hacer que esto funcione con 1.2, y realmente no intenté limpiar las partes internas. Ahora que tengo casos de prueba que prueban la API, puedo volver y limpiar eso más tarde.

Si lo está utilizando con ModelForms y desea la funcionalidad de guardar() tendrá que anular el método en su clase SuperForm.

Actualmente lo tengo localmente en mi repositorio "común" con un 90% de cobertura de código que cubre múltiples subformularios, formularios mixtos SubForms & declarados y ModelForms. He incluido los casos de prueba a continuación (tenga en cuenta que usa mi clase TestCaseBase, pero esto debería darle la esencia de la API). Avíseme si tiene alguna pregunta o sobre alguna área que haya olvidado.

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.']) 

Enjoy!

+0

Guau, eso es increíble! Muchas gracias :) Desafortunadamente esto llegó un poco tarde para mi proyecto actual (encontré otro sol'n), ¡pero tal vez para mi próximo! – mpen

+0

Sí, no hay problema. Gracias por hacer la pregunta y dar un buen punto de partida. Esto es algo que me hubiera sido útil durante mucho tiempo. En cuanto a su otra solución, ¿qué terminaste haciendo? Ah, ¿y gané la recompensa? :) – sdolan

+0

Seguro que sí. Supongo que tu código realmente funciona;) ¿Qué terminé haciendo? ¡Solo lo más estúpido que un programador puede hacer! ¡Reescribió la aplicación * whole * forms desde cero! – mpen