Ok, still slightly confused. First - a high level description. I have a field that contains choices, but when I display the select, I want to display some extra html below the select box, so I am creating a custom widget that displays the standard select followed by my html.
Question: If want to use a special widget for a ChoiceField, is it true that I need to instantiate the ChoiceField (or TypedChoiceField), rather than just setting the .widget attribute on the one that is by default created for me (due to it being a modelForm)? I find that if I just do this: self.fields["status"].widget = StatusWidget(task=instance) then my widget's select does not contain any choices. My widget doesn't do anything special to the select, it looks like this: class StatusWidget(widgets.Select): def __init__(self, task, attrs={}): self.task = task super(StatusWidget, self).__init__(attrs) def render(self, name, value, attrs=None): rendered = super(StatusWidget, self).render(name, value, attrs) rendered = rendered + .... add a bunch of stuff to the end return rendered Because I seem unable to display the choices correctly in the select box when I just set the field's widget attribute to my StatusWidget, I am instantiating the field itself. That now looks like this: self.fields["status"] = forms.TypedChoiceField (choices=Task.STATUS_CHOICES, widget=StatusWidget(task=instance), required=False, coerce=IntegerField.to_python) However, I see when debugging that IntegerField.to_python is an unbound method: (Pdb) self.coerce <unbound method IntegerField.to_python> What is the right thing to set coerce to if I just want it to do whatever it would "normally" do for the corresponding model field if I wasn't trying to override the widget? In my case I have verified that if I set coerce=int that does work, but that doesn't seem very general. I'd much rather use whatever the standard coerce method would have been if I hadn't overridden the widget. Margie On Aug 8, 12:11 am, Malcolm Tredinnick <malc...@pointy-stick.com> wrote: > Hi Margie, > > > > On Fri, 2009-08-07 at 23:17 -0700, Margie wrote: > > > Hmmm, ok, after digging around I realize that full_clean was not > > setting cleaned_data for the status field to an integer value; > > cleaned_data['status'] was just getting set to something like u'1'. > > > I am in fact using sqllite, and yes, my status fields are just > > integers: > > > OPEN_STATUS = 1 > > CLOSED_STATUS = 2 > > STALLED_STATUS = 3 > > > I think the problem has to do with the way I created the status field, > > which is like this: > > > self.fields["status"] = forms.ChoiceField > > (choices=Task.STATUS_CHOICES, widget=StatusWidget(task=instance), > > required=False) > > Right, that won't do what you want. ChoiceField normalizes to a unicode > object. > > > > > I tried moving to TypedChoiceField(), but that didn't help. I > > debugged into it in the case where I used TypedChoiceField() and I can > > see that when coerce is called it isn't doing anything, it is just > > returning the unicode value. > > > I find that if I do this instead, that it does do the coerce > > correctly: > > > self.fields["status"].widget = StatusWidget(task=instance) > > > In looking at the doc it looks like the purpose of TypedChoiceField() > > is to allow me to create my own coerce function, is that right? > > Correct. > > > And > > of course I wasn't doing that so it was behaving the same as > > ChoiceField, and it looks like the default there is to just return the > > unicode. > > Also correct. The documentation says "Defaults to an identity function" > and all the data coming from a form submission are strings (Python > unicode objects), so if you don't supply the coerce parameter, it does > nothing. > > It's probably a slight API wart that TypedChoiceField doesn't just raise > an exception if you don't supply coerce(). The default is slightly > dangerous, as it almost always means you're misusing the field. Not a > fatal flaw in the design, however. > > > > > When I don't declare the status field at all (ie, just let django do > > it's default thing), my guess is that it is choosing a coerce function > > based on the integer type of my choices, is that true? > > Yes. The django.db.models.fields.Field.formfield() method detects if you > have specified "choices" in the field and uses the Field subclass's > to_python() function as the coerce method. > > > I have never > > used anything but sqlite3 so far, so I guess that was masking the > > error and I would have run into this in a more serious way when I > > moved to a different db? > > Actually, my SQLite observation was entirely bogus. I suspect what > you're seeing is the difference between these two lines: > > t1 = Task.objects.create(status=u'3') > t2 = Task.objects.get(id=t1.id) > > In this case, t1.status will be a unicode string, but t2.status will > always be an integer, no matter what DB backend is involved. So you are > seemingly stumbling over a case like the t1 situation -- where you're > using the object after it has been populated and saved, but still using > the raw data. > > I've long argued that allowing the wrong types to be assigned to > attributes in Django models is a flaw (Python got rid of automatic type > coercion for operator arguments years ago for the same reason), but it's > been there forever in Django-years, so isn't going to go away now. > > 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 -~----------~----~----~----~------~----~------~--~---