Re: Bug with model get_*_display() methods?

2009-08-09 Thread Margie

Thanks for the pointers, that all make sense now.

Margie

On Aug 8, 6:47 pm, Malcolm Tredinnick 
wrote:
> On Sat, 2009-08-08 at 12:09 -0700, Margie wrote:
>
> [...]
>
> > 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)
>
> Grep'ing for "choices" in django/forms/*.py would reveal the answer to
> this. Have a look at how the Select widget handles choices, since that
> is what you're subclassing.
>
> The "choices" attribute of all the classes in widgets.py is set in the
> __init__() method of each widget. In fields.py, have a look at
> ChoiceField and you'll see that when you set choices on a field, they
> are also set on the associated widget (there's a _set_choices() method
> that is part of the "choices" property on ChoiceField).
>
> What you're doing in your above code is not setting any choices at all.
> You need to tell the widget which choices it can use.
>
> [...]
>
> > However, I see when debugging that IntegerField.to_python is an
> > unbound method:
>
> > (Pdb) self.coerce
> > 
>
> > 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.
>
> I'm not completely convinced this is a great plan, since if you are only
> overriding the widget in __init__, then the coerce function will already
> have been set up when the TypedChoiceField was created (it's a feature
> of the forms.Field subclass, not the widget). If you are overriding the
> form field entirely then you know better than Django what the correct
> type to use is, so it's actually easier and arguably clearer to just put
> in the right thing.
>
> However, you also have access to the model, so just use the
> model._meta.fields[...] entry for the field and use the to_python()
> method on that instance. Look at things like
> django.db.models.options.Options.get_field_by_name().
>
> 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
-~--~~~~--~~--~--~---



Re: Bug with model get_*_display() methods?

2009-08-09 Thread Margie

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  wrote:
> On Sat, Aug 8, 2009 at 2:09 PM, Margie 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
> > 
>
> > 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 
> > 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 

Re: Bug with model get_*_display() methods?

2009-08-08 Thread Malcolm Tredinnick

On Sat, 2009-08-08 at 12:09 -0700, Margie wrote:
[...]
> 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)

Grep'ing for "choices" in django/forms/*.py would reveal the answer to
this. Have a look at how the Select widget handles choices, since that
is what you're subclassing.

The "choices" attribute of all the classes in widgets.py is set in the
__init__() method of each widget. In fields.py, have a look at
ChoiceField and you'll see that when you set choices on a field, they
are also set on the associated widget (there's a _set_choices() method
that is part of the "choices" property on ChoiceField).

What you're doing in your above code is not setting any choices at all.
You need to tell the widget which choices it can use.


[...]
> However, I see when debugging that IntegerField.to_python is an
> unbound method:
> 
> (Pdb) self.coerce
> 
> 
> 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.

I'm not completely convinced this is a great plan, since if you are only
overriding the widget in __init__, then the coerce function will already
have been set up when the TypedChoiceField was created (it's a feature
of the forms.Field subclass, not the widget). If you are overriding the
form field entirely then you know better than Django what the correct
type to use is, so it's actually easier and arguably clearer to just put
in the right thing.

However, you also have access to the model, so just use the
model._meta.fields[...] entry for the field and use the to_python()
method on that instance. Look at things like
django.db.models.options.Options.get_field_by_name().

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
-~--~~~~--~~--~--~---



Re: Bug with model get_*_display() methods?

2009-08-08 Thread Alex Gaynor

On Sat, Aug 8, 2009 at 2:09 PM, Margie 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
> 
>
> 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 
> 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 

Re: Bug with model get_*_display() methods?

2009-08-08 Thread Margie

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


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 
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 

Re: Bug with model get_*_display() methods?

2009-08-08 Thread Malcolm Tredinnick

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
-~--~~~~--~~--~--~---



Re: Bug with model get_*_display() methods?

2009-08-08 Thread Margie


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)

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?  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.

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?  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?

Ok, cool, learn something new every day.  Thanks for you pointers, if
you can just yay or nay my hypotheses above, that'd be cool.

Margie

On Aug 7, 7:39 pm, Malcolm Tredinnick 
wrote:
> On Fri, 2009-08-07 at 11:40 -0700, Margie wrote:
> > I see inconsistencies in how get_*_display() works based on whether
> > the object is a recently saved object.  Probably an example describes
> > this best:
>
> > My model contains this:
>
> > class Task(models.Model):
>
> >     STATUS_CHOICES = (
> >         (OPEN_STATUS, 'Open'),
> >         (CLOSED_STATUS, 'Closed'),
> >         (STALLED_STATUS, 'Stalled'),)
>
> >     status = models.IntegerField(choices=STATUS_CHOICES, blank=True,
> > null=True)
>
> I'm assuming OPEN_STATUS and friends are integers here (and not '1' or
> other strings that contain integers).
>
> [...]
>
> > However, if I have recently saved a modelForm associated with my Task
> > model and now have a handle to the object that that save() returned,
> > the status is in unicode, and get_status_display() doesn't return a
> > useful string:
>
> > (Pdb) type(self)
> > 
> > (Pdb) self.status
> > u'3'
> > (Pdb) self.get_status_display()
> > u'3'
>
> If I create a standard ModelForm subclass for your task model and then
> submit some data to it (just using {"status": "1"} as the POST data
> dictionary), I cannot replicate your problem.
>
> The devil is in the details here. What does your ModelForm look like?
>
> The results you are seeing are consistent with the form somehow saving a
> string value for the "status" field. Which means (a) you're using
> SQLite, since other databases will complain about the type mismatch, and
> (b) something is going funky in your particular ModelForm.
>
> The get_FOO_display() method requires an exact match the choice value
> and the value of the field, otherwise it just returns the field value.
> Since 3 != u'3' in Python, it is returning the correct result, given the
> value of the status field. The question is how did you manage to get a
> string into the status field.
>
> 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
-~--~~~~--~~--~--~---



Re: Bug with model get_*_display() methods?

2009-08-07 Thread Malcolm Tredinnick

On Fri, 2009-08-07 at 11:40 -0700, Margie wrote:
> I see inconsistencies in how get_*_display() works based on whether
> the object is a recently saved object.  Probably an example describes
> this best:
> 
> My model contains this:
> 
> class Task(models.Model):
> 
> STATUS_CHOICES = (
> (OPEN_STATUS, 'Open'),
> (CLOSED_STATUS, 'Closed'),
> (STALLED_STATUS, 'Stalled'),)
> 
> status = models.IntegerField(choices=STATUS_CHOICES, blank=True,
> null=True)

I'm assuming OPEN_STATUS and friends are integers here (and not '1' or
other strings that contain integers).

[...]
> However, if I have recently saved a modelForm associated with my Task
> model and now have a handle to the object that that save() returned,
> the status is in unicode, and get_status_display() doesn't return a
> useful string:
> 
> (Pdb) type(self)
> 
> (Pdb) self.status
> u'3'
> (Pdb) self.get_status_display()
> u'3'

If I create a standard ModelForm subclass for your task model and then
submit some data to it (just using {"status": "1"} as the POST data
dictionary), I cannot replicate your problem.

The devil is in the details here. What does your ModelForm look like?

The results you are seeing are consistent with the form somehow saving a
string value for the "status" field. Which means (a) you're using
SQLite, since other databases will complain about the type mismatch, and
(b) something is going funky in your particular ModelForm.

The get_FOO_display() method requires an exact match the choice value
and the value of the field, otherwise it just returns the field value.
Since 3 != u'3' in Python, it is returning the correct result, given the
value of the status field. The question is how did you manage to get a
string into the status field.

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
-~--~~~~--~~--~--~---



Bug with model get_*_display() methods?

2009-08-07 Thread Margie

I see inconsistencies in how get_*_display() works based on whether
the object is a recently saved object.  Probably an example describes
this best:

My model contains this:

class Task(models.Model):

STATUS_CHOICES = (
(OPEN_STATUS, 'Open'),
(CLOSED_STATUS, 'Closed'),
(STALLED_STATUS, 'Stalled'),)

status = models.IntegerField(choices=STATUS_CHOICES, blank=True,
null=True)


If I get a Task object from the database (via a .get() or .filter()),
then my status field contains an integer and I can call
the .get_status_display() method, ie:

(Pdb) type(t)

(Pdb) t.status
3
(Pdb) t.get_status_display()
u'Stalled'


However, if I have recently saved a modelForm associated with my Task
model and now have a handle to the object that that save() returned,
the status is in unicode, and get_status_display() doesn't return a
useful string:

(Pdb) type(self)

(Pdb) self.status
u'3'
(Pdb) self.get_status_display()
u'3'

Is this expected behavior?

Margie


--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---