tags:

views:

156

answers:

1

Basically I have a model with a ManyToMany field, and then a modelform derived from that model where that field is rendered as a "multiple choice" selectbox. In my template I'm having that field omitted, electing instead to prepare the values for that field in the view, then pass those prepared values into request.POST (actually a copy of request.POST because request.POST is immutable), then feeding request.POST to the form and then carry on as normal. I can't figure out how to do this, because request.POST isn't just a simple python dictionary, but instead a QueryDict, which behaves a little differently.

The field I need to populate is called "not_bases". When I create the widget using the form, it works perfectly well internally, but just not to my liking UI-wise. When I inspect the django-form submitted POST value via django's handy debug error window, the working QueryDict looks like this:

<QueryDict: {u'not_bases': [u'005', u'00AR', u'00F', u'00FD'], [...] }>

It appears the value for "not_bases" is a list, but it's not simply a list. I can't just .append() to it because it won't work. I dug around the documentation and found .update(), which appears to work, but doesn't. Here is my code:

newPOST = request.POST.copy()
for base in bases:
 newPOST.update({"not_bases": base.identifier})

and here is the output:

<QueryDict: {u'not_bases': [u'KMER', u'KYIP'], u'reference': [u''], [...] }>

But when I feed that QueryDict to the form, I get an form validation error that says "not_bases: Enter a list of values.". Its obvious that the list-looking things coming from the str() representation of the QueryDict are not the same in the two cases above, even though they look exactly the same

So how do I do this?

+2  A: 

It's really not clear what you're trying to do here, but I doubt that hacking the QueryDict is the right way to achieve it.

If you are trying to customise the display of the not_bases field, you can simply override the definition in your modelform declaration:

class MyModelForm(forms.ModelForm):
    not_bases = forms.ChoiceField(choices=[(base, base) for base in bases])

    class Meta:
         model = MyModel

Or, if you simply want to avoid showing it on the form, you can exclude it from the form and set the value after validation.

class MyModelForm(forms.ModelForm):

    class Meta:
         model = MyModel
         exclude = ['not_bases']


....
if request.POST:
     if form.is_valid():
         instance = form.save(commit=False)
         instance.not_bases = bases
         instance.save()

Does either of these do what you want?

Daniel Roseman
I my actual code, I have "not_bases" as well as about 5 other "XXX_bases" fields. The catch is that a Base object can only exist in one and only one those fields. In order to do this, I have the form not drawl those "XX_fields" and instead make my own using radio buttons. I wrote a little bit of code that goes through my custom fields in the POST data, and creates a list for each field. I _could_ add them after a commit=False, but while I'm looping and making lists, why not just add it to request.POST? Just saves a step...
nbv4