简体   繁体   English

Django复合/嵌套/子表单?

[英]Django compound/nested/subforms?

I'm looking for an updated version of these Django SuperForms . 我正在寻找这些Django SuperForms的更新版本。 Can't seem to get it to work in Django 1.2. 似乎无法在Django 1.2中使用它。 In particular, I'd like it to work with ModelForms. 特别是,我希望它能与ModelForms一起使用。

My use case is almost identical to his; 我的用例几乎与他的用例相同; I have an Address model that I'd like to use as a sub-form in various places. 我有一个Address模型,我想在各个地方用作子表单。 It's a pain to try and combine everything in the view func. 尝试在视图函数中组合所有内容是一种痛苦。

I've updated superforms.py to work w/1.2, and attached it to the ticket you linked to: http://code.djangoproject.com/attachment/ticket/3706/superform.2.py 我已经更新了superforms.py以使用w / 1.2,并将其附加到您链接到的票证: http//code.djangoproject.com/attachment/ticket/3706/superform.2.py

There's a project I'm working on that could benefit from this, so I figured I'd spend the time and help you out as well. 有一个我正在研究的项目可以从中受益,所以我想我也会花时间帮助你。

Keep in mind that I just got this to work w/1.2, and didn't really try to clean up the internals. 请记住,我只是在1.2版本上工作,并没有真正尝试清理内部。 Now that I have test cases proving the API, I can go back and clean that up later. 现在我已经有了证明API的测试用例,我可以稍后再回过头来清理它。

If you're using it with ModelForms and you'd like the save() functionality you'll have to override the method on your SuperForm class. 如果您将它与ModelForms一起使用并且您想要save()功能,则必须覆盖SuperForm类上的方法。

I currently have it locally in my "common" repository w/~90% code coverage that covers multiple SubForms, mixed SubForms & declared forms, and ModelForms. 我目前在我的“通用”存储库中本地拥有它,包含多个子表单,混合子表单和声明表单以及ModelForms的90%代码覆盖率。 I've included the test cases below (beware it uses my TestCaseBase class, but this should give you the gist of the API). 我已经在下面包含了测试用例(请注意它使用我的TestCaseBase类,但这应该为您提供API的要点)。 Let me know if you have questions, or any areas I missed. 如果您有任何问题或我遗漏的任何方面,请告诉我。

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! 请享用!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM