modelformset_factory, initial, and queryset

1,503 views
Skip to first unread message

Tim Valenta

unread,
Oct 14, 2010, 5:32:49 AM10/14/10
to Django users
This is driving me mad, so I must ask the community, in hopes of a
workaround:

I've got a simple formset of models on a page, generated by
modelformset_factory. This particular page will never create forms--
it only modifies existing ones. Therefore the queryset I pass into
the formset constructor gets built, and everything works great.

I've added a field to the formset, but Django seems perfectly happy to
totally ignore whatever initial data I want to supply for this
'virtual' field that I've added. It seems that I've got absolutely no
mechanism for setting a dynamically-generated value as a pre-computed
field value.

My situation is that I want to represent an many-to-many relationship
on this 'virtual' field, which doesn't actually exist on my model.
When the form is submitted, I can easily intercept the values sent and
do what I will with them. However, when the page refreshes after a
submission, I cannot for the life of me inject this data back into the
form. As of right now, my select-multiple widget is quite blank, no
matter what I do.

Help? I've literally been at this for hours off and on.

Daniel Roseman

unread,
Oct 14, 2010, 6:09:34 AM10/14/10
to Django users
Can you show some code? It would help to understand what you're doing.
--
DR.

Tim Valenta

unread,
Oct 15, 2010, 11:36:18 PM10/15/10
to Django users
I have a model like such:
class Response(models.Model):
raw_text = models.TextField()
respondent = models.ForeignKey('auth.User')

Response has a related model attached to it:
class Code(models.Model):
response = models.ForeignKey(Response)
coded_answer = models.IntegerField()

The idea is that Responses come in as typed text, and then are
processed and assigned standardized Codes to represent the meaning
contained in the text.

Now, it greatly simplifies my life if I can use a normal formset to
represent the main Response objects gathered on a page for processing,
using the 'queryset' parameter to scope the Responses being handled.
I'm making use of the admin's filtered select widget in a ModelForm
for the Response model, like so:
class ResponseCodingForm(forms.ModelForm):
codes = forms.MultipleChoiceField(choices=[yada yada],
widget=FilteredSelectMultiple('Codes', false))
class Meta:
model = Response
fields = ['raw_text']

As you can see, the form only represents the "raw_text" field, but
adds a virtualized field called "codes" to the mix, which I want to
manage myself. That is, I want to inject data values into it when I
create my formset, as you will soon see. This approach works great
for when I render the formset, properly placing a field for "codes" on
my forms. Naturally, the value of this field gets POSTed back to my
view, which I happily read from my form's cleaned_data attribute,
processing as I see fit.

But when it comes time to instantiate my formset, I can't find a way
to pump my own values into this "codes" field on the form. Here is
the relevant part of the view:
responses = Response.objects.filter( yada yada)
ResponseCodingFormSet = modelformset_factory(Response,
form=ResponseCodingForm, extra=0)
initial = [{
'codes': list(response.code_set.values_list('id', flat=True)),
} for response in responses]

if request.method == 'POST':
# handle validation and save operations
else:
formset = ResponseCodingFormSet(queryset=responses,
initial=initial)


I realize that what I'm doing could be handled by some inline
formsets, but I really wanted to leverage that FilteredSelectMultiple
widget to represent my related model association.

No matter what I do, the formset's value for any of the objects'
"codes" field is empty.

Daniel Roseman

unread,
Oct 17, 2010, 5:36:07 AM10/17/10
to Django users
That's strange. I've just run the same code myself and have found that
the 'codes' field was populated properly, with the IDs of the
associated objects selected.

The only thing I can think of is that the choices for the field are
not being set correctly to start with - in the bit where you write
`(choices=[yada yada]`, what is 'yada yada'? Obviously, this must
contain *all* possible values for the codes across all responses, so
that the relevant ones can be selected for each item in the formset.
--
DR.

Tim Valenta

unread,
Oct 17, 2010, 11:57:51 AM10/17/10
to django...@googlegroups.com
Sir, I just re-examined my code and realized that the integers I was
plugging into `initial` was the wrong value, semantically speaking.
IDs from the wrong model were being used for initial values...
Simplifying my example for this explanation helped me see that pretty
quickly when I pulled my code up just now.

Thanks for the second pair of eyes! I knew of course that the
`initial` keyword argument worked in my other views, but I doubted
myself. Surprising how many really lame mistakes you can make even
after a couple years of using Django every day!

Tim

On Sun, Oct 17, 2010 at 08:38, Tim Valenta <tonights...@gmail.com> wrote:
>> The only thing I can think of is that the choices for the field are
>> not being set correctly to start with - in the bit where you write
>> `(choices=[yada yada]`, what is 'yada yada'? Obviously, this must
>> contain *all* possible values for the codes across all responses, so
>> that the relevant ones can be selected for each item in the formset.
>

> I had shortened it because it was a gross little bit of code which
> effectively takes a queryset of another model and turns them into a
> customized "choice" strings.  The result is just a giant tuple of (id,
> "name") pairs, where the `id` is the value I'm interested in injecting
> into the `codes` field.  You are right about it needing to contains
> *all* possible codes.
>
> Did your test work for just `extra` forms, or did it also work out for
> existing instances?  The part that kills me as I test is that I have
> poked around in the field object after I try to set the `initial`
> values, and my inserted ids are there among the other initial values
> from the instance value, yet `codes` would just not show up on my the
> form.
>
> If it works for you, then I really need to break this down and examine
> more contextual details!
>
> Thanks for the input.
>

Tim Valenta

unread,
Oct 17, 2010, 11:38:22 AM10/17/10
to django...@googlegroups.com
> The only thing I can think of is that the choices for the field are
> not being set correctly to start with - in the bit where you write
> `(choices=[yada yada]`, what is 'yada yada'? Obviously, this must
> contain *all* possible values for the codes across all responses, so
> that the relevant ones can be selected for each item in the formset.

I had shortened it because it was a gross little bit of code which

Reply all
Reply to author
Forward
0 new messages