Right - of course.  Don't ask me why didn't realize to use IntegerField
().to_python myself ...

Margie

On Aug 8, 12:32 pm, Alex Gaynor <alex.gay...@gmail.com> wrote:
> On Sat, Aug 8, 2009 at 2:09 PM, Margie<margierogin...@yahoo.com> wrote:
>
> > 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 can just set coerce to `IntegerField().to_python`, here you can
> instantiate a dummy IntegerField instance to use.
>
> Alex
>
> --
> "I disapprove of what you say, but I will defend to the death your
> right to say it." -- Voltaire
> "The people's good is the highest law." -- Cicero
> "Code can always be simpler than you think, but never as simple as you
> want" -- Me
--~--~---------~--~----~------------~-------~--~----~
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