Following the django documentation I try to make a choices field in my models.py:
class MyModel(Model):
ACTION_CHOICES = (
('d', 'delete'),
('c', 'create'),
('u', 'update'),
)
action = CharField(max_length=1, choices=ACTION_CHOICES)
But when I run it with
action = MyModel(action='create')
action.save()
and check the database the action is not c
, but create
. Furthermore even restriction to max_length doesn't affect on it. Ok, I moved on and tried to make it in this way:
models.py
class MyModel(Model):
ACTION_CHOICES = (
(1, 'delete'),
(2, 'create'),
(3, 'update'),
)
action = IntegerField(max_length=1, choices=ACTION_CHOICES)
code.py:
action = MyModel(action='create')
action.save()
But I got an error that str field can't be saved like int (database has the int field, but MyModel.action is str) What Do I miss here? Aren't choices supposed to convert value on save?
Best regards,
There are several questions in your post:
1) The choices
can only restrict what can be entered through a Django form. When you manually instantiate your object you can insert any value. So
action = MyModel(action='create')
actually inserts the string create
into the action column.
2) Normally max_length
should stop you from inserting a string longer than 1 character into that column, but I guess you are using SQLite which has no restriction on VARCHAR lengths.
3) Django has no easy conversion from the display values to choice keys. You can have a look at django-model-utils for a wrapper on choices.
When you define choices
ACTION_CHOICES = (
(1, 'delete'),
(2, 'create'),
(3, 'update'),
)
the values stored in the db are 1, 2, 3, while 'delete', 'create' etc.. are just labels, just to explain, the prev choices results in such select input element:
<select>
<option value="1">delete</option>
<option value="2">create</option>
<option value="3">update</option>
</select>
Choices are not supposed to convert value on save, are supposed to map db values with labels, and used when rendering the form widget and when retrieving the field representation (get_field_display). But if you set directly the value of a column it doesn't play a role.
If you want to use "talking keys" you can define them as class properties, like
class MyModel(models.Model):
DELETE_ACTION = 1
CREATE_ACTION = 2
UPDATE_ACTION = 3
ACTION_CHOICES = (
(DELETE_ACTION, 'delete'),
(CREATE_ACTION, 'create'),
(UPDATE_ACTION, 'update'),
)
Then you can do
action = MyModel(action=MyModel.CREATE_ACTION)
and it would be fine
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With