I want to show the human-readable name for the type selected but I keep getting the stored value.
TYPE_CHOICES = (
('0', 'Basic'),
('1', 'Full'),
('2', 'Intermediate'),
)
class ServiceType(models.Model):
type = models.IntegerField(max_length=1, choices=TYPE_CHOICES)
开发者_如何转开发 amount = models.DecimalField(max_digits=10, decimal_places=2)
def __unicode__(self):
return '%s' % (self.get_type_display())
It seems that you have your answer, but as another link, I'd just like to point out James Bennett's thoughts on this: Handle choices the right way
I think it is a pretty convenient way to do things, and removes the 'magic number' aspect of things. Worth a read IMO, even if you go for a different option.
From his article (quoted in case it disappears):
class Entry(models.Model):
LIVE_STATUS = 1
DRAFT_STATUS = 2
HIDDEN_STATUS = 3
STATUS_CHOICES = (
(LIVE_STATUS, 'Live'),
(DRAFT_STATUS, 'Draft'),
(HIDDEN_STATUS, 'Hidden'),
)
# ...some other fields here...
status = models.IntegerField(choices=STATUS_CHOICES, default=LIVE_STATUS)
Now we can just import the Entry model and query like so:
live_entries = Entry.objects.filter(status=Entry.LIVE_STATUS)
draft_entries = Entry.objects.filter(status=Entry.DRAFT_STATUS)
You probably want to use ChoiceField instead of IntegerField in your model. It sounds like you are seeing an input tag with type=text in your admin but want a select tag. The default widget associated with a IntegerField is TextInput which would explain what you are seeing.
Another option is to write your own admin and explicitly call out that you want type to be a ChoiceField in the admin. Something like this:
class ServiceTypeAdmin(admin.ModelAdmin):
# ...
type = fields.ChoiceField(choices=TYPE_CHOICES)
admin.site.register(ServiceType, ServiceTypeAdmin)
I would personally start by switching the IntegerField to a ChoiceField. Way less work involved.
I had that same problem, and couldn't figure out why it works, but if you change the field type to CharField the get_type_display should work fine.
TYPE_CHOICES = (
('B', 'Basic'),
('F', 'Full'),
('I', 'Intermediate'),
)
class ServiceType(models.Model):
type = models.CharField(max_length=1, choices=TYPE_CHOICES)
amount = models.DecimalField(max_digits=10, decimal_places=2)
Rookie mistake, I've changed the tuple values from ('0', 'Basic) to (0, 'Basic') and it worked. I didn't realize that I was saving a char value as an integer value.
Thanks for your help.
Trick
use TypedChoiceField()
The answer of your questoin lies in using TypedChoiceField
, not ChoiceField
.
you are getting type field from a django form
, using the cleaned_data
from a ChoiceField
. The problem with this is that the output from a ChoiceField
is a string, not an integer.
if you use get_type_display()
right after saving the form, u would probably get the value, but when u have try to retrieve the value from the DB, you would get integer
instead of string(because your are saving type as Integer field), here you wont be able to get value with get_type_display.
Having now looked into this, I see that you should have used the TypedChoiceField
, to ensure that the output from cleaned_data is always an integer or string.
first of all change IntergerField
to Char field or SmallIntergetField
.
Hope this helps.
Code
type = models.SmallIntegerField(choices=TYPE_CHOICES)
in forms.py
type = TypedChoiceField(coerce=int, required=False, empty_value=0, choices=TYPE_CHOICES)
another possibility is that you could use MODELFORM
and provide the widgets
for the field.
Forms.py
class abc(forms.Modelform)
class Meta:
model = FOO
widgets = {
'type': forms.TypedChoiceField(coerce=int, required=False, empty_value=0, choices=TYPE_CHOICES),
type
shadows with an in-built bulletin
, that's why get_type_display()
has no effects. Avoid using column names as type
instead use service_type
or something else and use get_service_type_display()
i.e get_<column_name>_display()
.
精彩评论