On Wed, 2009-03-04 at 00:28 -0800, Margie wrote: [...] > After debugging into the source some more, I'm finding that my the > problem is related to the fact that empty_permitted is getting set to > True when all of my forms are considered "extra.
Which is reasonable. "Extra" here means "optional". > Specifically, in site- > packages/django/forms/forms.py, in the full_clean() function, I find > that when empty_permitted is set to True, this code executes, which > drops me out of the code without setting cleaned_data at all: > > # If the form is permitted to be empty, and none of the form > data has > # changed from the initial data, short circuit any validation. > if self.empty_permitted and not self.has_changed(): > return This will only happen if none of the data has changed. That's the point of the call to has_changed(). > It seems to me that if I pass in initial when I create the > TaskTileDetailFormSet, ie, like this: > > initial = [] > for tile in tileList: > initial.append({'tile': tile.id}) > > taskTileDetailFormSet = TaskTileDetailFormSet(data, > tiles=tileList, initial=initial) > > then empty_permitted gets set to False ibecause my initial_form_count > is non-zero. IE, in site-packages/django/forms/formsets.py, in > _construct_form(), in thh code that looks like this: > > # Allow extra forms to be empty. > if i >= self._initial_form_count: > defaults['empty_permitted'] = True > > But if I pass initial in via my own _construct_form() function as you > suggested, then I have no initial data, so all of my forms are > "extra". IN this case self._initial_form_count is 0, and it seems > that the result is that cleaned_data doesn't get set correctly. That would only be the case if none of the data for the form has changed. If you've changed something on the form (from the initial data's perspective), has_changed() should be returning True. > > I am probably far from undrestanding this, but if what I said is > atually true, it seems like this is actually a bug? The bug being > that cleaned_data is not getting set correctly when the forms are > created as "extra" forms. Perhaps cleaned_data is not supposed to get > set in this case? Formsets are not entirely broken. Let's not think of zebras in preference to horses when we hear the hoof-beats. If formsets and empty forms didn't work, the entire admin application would be broken in interesting ways, for example. You've found the right pieces of code, but you aren't examining why they are falling through to skipping validation. The conditional test is important. Why isn't has_changed() returning True for your particular setup? Do you have to also subclass that based on the data changes you're making, perhaps? > The whole reason that I happened upon this is > beacuse I am trying to identify which form is which, so I was looking > at cleaned_data['tile']. I set that myself anyway, so I can just look > at data['tile']. This is something I don't understand. If you are setting up the "tile" each time in your view, why is it having to be sent to the form? Either it's data you take from the form, or it's data you can always supply in the view. I've decided I don't understand the problem you're trying to solve here, so can you please (re-)explain that? I've gone back over the thread and I can't see a clear statement of the need for all this customisation, so thinking of alternative approaches is hard. Once you have somehow identified the formset, identifying each form inside it doesn't seem to be necessary, particularly if they're all new objects (after all, each form in the formset is numbered, so unique identifier + offset in formset is a unique way of identifying each component form). Why not just have a single identifier for the entire formset? If you can do that, then the problem falls out easily: the identifier doesn't go in the formset at all. It goes into a separate form class that only contains this hidden field. Remember that Django form classes correspond to a fragment of an HTML form, so you can pass multiple form instance (or a form instance plus a formset instance) to the template. Alternatively, you could override Formset.__init__ and put the identifier into the ManagementForm instance. That doesn't feel quite as nice to me, since it's kind of relying on a bunch of implementation details (I'd almost like ManagementForm to be overridable, probably as a class attribute). Regards, Malcolm --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---