On Tue, 2009-03-03 at 22:42 -0800, Margie wrote: > Hi Malcolm - Sorry, another formset question. Maybe you'll know the > answer offhand, have been trying to figure this out for awhile now. > I'm trying to set the initial value for a form field inside the > constructor for the form. The high level goal is to send out the > 'tile' field as a hidden input so that I can get it back in the POST > so that I can figure out wich 'tile' each form in the forset > corresonds to. > > For example, I'm trying to do this in my form constructor > (specifically see the ==> line) > > class TaskTileDetailForm(forms.ModelForm): > class Meta: > model=TaskTileDetail > exclude=('task')
If this is a cut-and-paste, this line is almost certainly a bug. The "exclude" parameter should be a tuple or a list, so ("task",) or ["task"] (note the trailing comma in the tuple case). > > def __init__(self, tile, *args, **kwargs): This line is a probably going to be a problem at some point. You cannot just add new positional arguments into the front of the __init__ call like this. When Django calls the constructor, it could well be passing the "data" parameter as the first argument. Instead, pass it in as a keyword argument. To wit: def __init__(self, *args, **kwargs): tile = kwargs.pop("tile") super(TaskTileDetailForm, self).__init__(*args, **kwargs) ... That preserves the ordering of positional arguments. > super(TaskTileDetailForm, self).__init__(*args, **kwargs) > self.fields['tile'].widget = forms.HiddenInput() > ==> self.fields['tile'].initial = tile.id > > If I do this, then later when processing my POST data there is no > 'tile' key in cleaned_data. IE, I get a KeyError when I do this: > if taskTileDetailForm.cleaned_data["tile"] in taskTiles: > > If I intiaizize it with the initial arg when creating the formset, the > cleaned_data["tile"] key is set just fine, ie when I use initial as > shown at the ==> below: It seems like the problem is how is "tile" meant to be known to each form? When a formset is constructed, it just constructs and essentially normal form, passing in any "data" and "initial" parameters. If you need to do any extra setup on the form -- particularly dealing with passing in extra parameters -- then you have to do something similar to what I did in my blog post ([1], for those who don't know what we're talking about). So, either, pass in "initial" to the formset, or override the _construct_form() method, as in the blog post. That's precisely why I had to do it that way in my example: I needed to pass in some custom information to each form as it was constructed as part of the formset. The difference between your case and mine, is that your extra data corresponds directly to a form field (in mine, the question text was auxiliary data that wasn't a form field). So I would probably set it up using the "initial" parameter, if it was me. It would involve far less formset base class customisation. [1] http://www.pointy-stick.com/blog/2009/01/23/advanced-formset-usage-django/ > def makeTaskTileDetailFormSetForCreate(tileList, data=None): > TaskTileDetailFormSet = formset_factory > (form=TaskTileDetailForm, formset=CustomBaseFormSe) > > initial = [] > for tile in tileList: > initial.append({'tile': tile.id}) Since this is a read-only attribute, you could probably just write initial = [{"tile": tile.id}] * len(tileList) That will make each element of initial a reference to the same dictionary, but that's not a problem since the initial data is only read, never changed. 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 -~----------~----~----~----~------~----~------~--~---