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
-~----------~----~----~----~------~----~------~--~---

Reply via email to