Hi Chris, I've definitely faced similar issues. A few scattered thoughts below:
On 03/18/2014 02:54 PM, Chris Wilson wrote: [snip] > 1. GCBV and Vanilla Views do a great job for simple forms, but they > leave out embedded formsets entirely. (For example our large form has > repeating sections for employment history, education, etc.) It feels > like it would be great to have formsets handled "more automatically" - > instantiating, validating and saving them just like we do for forms. A > lot of our code is shared between all our formsets, and potentially > reusable. The approach I've used for this is encapsulating the creation and handling of the inline formsets entirely within the "parent" form class, so from the perspective of the view it acts like a normal simple form. This requires overrides of a few methods on the parent form: __init__() to create the formsets, is_valid() to ensure the formsets are valid too, has_changed() to see if formsets have changed, and save() to save formsets too. If we were going to look at incorporating something into Django, I'd like to consider this option as an alternative to adding more GCBVs with inline-formset support. I think it's a nicer abstraction (because in a real sense those inlines are "part of" the parent form), and I don't think we want to add to the already-extensive list of GCBVs and mixin classes. I think either approach would be workable as a third-party project, too. > 2. Adding instances to a formset on the client side using Javascript. > There is a django-formset-js package on PyPI, but it requires special > attributes to be added to form elements that would have been difficult > with crispy forms (which we're also using) and it feels almost like this > functionality ought to be in Django core (maybe not today, but one day?) I've used this: http://plugins.jquery.com/django-superformset/ I am skeptical of adding things to Django core that can be implemented mostly or entirely on the front-end. Django is a server-side framework. I think changes to the forms library that make it easier to implement such client-side libraries is a better place to start. > 3. We couldn't change the "extra" of a formset without redefining the > formset class. We wanted to do this because the required repeating > sections (employment history etc.) must not have a blank form in them if > they already have some valid forms, otherwise the blank forms prevent > the form being submitted because HTML5 client-side validation fails. So > we had to do all this: > > def get_context_data(self, **kwargs): > ... > for name, formset_class in self.formsets.iteritems(): > # doesn't exist yet, so we can't call its queryset() method > queryset = formset_class.model._default_manager.filter( > **{formset_class.fk.name: application}) > extra = 0 if queryset.exists() else 1 > > # need to reconstruct the formset class to change extra? > formset_class = inlineformset_factory( > Application, > formset_class.model, > formset_class.form, > formset_class, > extra=extra, > can_delete=formset_class.can_delete, > fields=formset_class.form.base_fields.keys(), > max_num=formset_class.max_num, > ) I don't understand this. The 'extra' attribute of a formset class can be tweaked dynamically as a normal attribute (although this may not be documented); it doesn't require recreating the entire formset class. I snipped your last three items, regarding saving invalid forms. I think this is an unusual use case, and I'm not sure support for it belongs in core. It would be interesting to experiment with something to make filefields less painful when validation fails, but that can be a third-party project first I think. Carl
signature.asc
Description: OpenPGP digital signature
