Hi all, As far as I'm aware (from browsing the mailinglists and the newforms code) newforms currently does not support compound or nested forms. With this I mean something like (fairly dumbed-down example, but taken from an app I'm currently working on):
class AddressForm(forms.Form): street = forms.CharField() city = forms.CharField() class BusinessLocationForm(forms.SuperForm): organisation = forms.CharField() visiting_address = forms.SubForm(AddressForm) postal_address = forms.SubForm(AddressForm, required=False) Currently I could copy/past the fields of AddressForm directly into the BusinessLocationForm. Or I'd have to create three separate forms (using prefixes) in my view and deal with it manually (subclassing BusinessLocationForm from AddressForm would only help if I'd only have the need for one address). In the past I've done some work with FormEncode, and that allows the exact use-case I've sketched above. That worked well, so I thought, may be I can add that functionality to newforms. So currently I've a (more or less working) implementation of what I've called a SuperForm, which can take either Fields or SubForms as shown above. The resulting form instance then behaves like any normal form. Clean_data becomes a dict of dicts so that you can easily take out all data related to a particular subform. E.g. in the above case you would get something like: ------------------------------------------------------------------------------------------------------------------ # create form instance f = BusinessLocationForm() # render the form, casauses all subforms to be rendered as well f.as_table() # the form elements are named as follows (using prefixes) # organisation # visiting_address-street # visiting_address-city # postal_address-street # postal_address-city # have user submit form and ... # receive data and create bound form f = BusinessLocationForm(request.POST) # validate, all subforms are validated as well, unless they're not required AND empty # in which case they're ignored if f.is_valid(): # assume AddressRecord and BusinessLocation are models closely matching # the presented forms # create a address record for visiting_address f.clean_data['visiting_address'] = AddressRecord(f.clean_data['visiting_address']) f.clean_data['postal_address'] = AddressRecord(f.clean_data['postal_address']) business_location = BusinessLocation(f.clean_data) ------------------------------------------------------------------------------------ The above example is very dumbed down but I guess you get the idea. The code after "is_valid" could perhaps be made more generic and put in a default SuperForm.save method. But maybe that's trying to be too smart. In any case you could put it there yourself, just to make the view code cleaner - in which case you'd just do: if f.is_valid(): f.save() Apart from the SubForm "field" I've also created a FormList "field" which takes a form definition, a min_count and a max_count which allows for easy creation of a whole list of identical forms (think edit_inline=models.STACKED). The SuperForm class I refer to by the way, is in fact a container for a number of forms that mimics the behaviour of a normal form. All subforms are stored in a SortedDict. I've taken a copy of BaseForm and reimplemented all methods to do the right thing to all subforms. If you add normal Fields to a SuperForm, those are collected and turned into another regular Form, which then in turn is added to the dict of subforms maintained by SuperForm. Since a SuperForm acts entirely as a normal Form you can also nest SuperForms. So you could do: ------------------------------------------------------------------------------------------------- class OrganisationForm(forms.SuperForm): name = forms.CharField() headquarters = forms.SubForm(BusinessLocationForm) other_locations = forms.FormList(BusinessLocationForm, min_count=1, max_count=10, required=False) f = OrganisationForm(request.POST) # clean_data['other_locations'] would be a list for location_data in f.clean_data['other_locations']: location = BusinessLocation(location) location.save() ... ... ------------------------------------------------------------------------------------------------- My questions now boil down to: Do any of you think of this as a desirable feature, if so do you agree with the road I've taken? Is anyone else already working on this? If there's desire and no objections I'll produce a cleaned up version and submit it in Trac. That could either be as e.g. contrib.superform or as a "patch" against newforms - I put "patch" between quotes because the existing newforms code is not touched in anyway, it's totally "bolt-on" in the form of a number of new classes. Rgds, Jeroen --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~----------~----~----~----~------~----~------~--~---