I want a primary key for my model to be unsigned. Therefore I do something like this:
class MyModel(models.Model):
id = models.PositiveIntegerField(primary_key=True)
This gets me an UNSIGNED
column in the resulting MySQL table, which I want. However, I believe I will not get the automatic assigning to id
each time I create a new object, will I? This seems to require the use of AutoField
instead. Problem is, AutoField
is signed. Is there a way to create an unsigned AutoField
?
The actual type of the field is specified in the backend. In the case of MySQL, the backend is django.db.backends.mysql
. This extract from django/db/backends/mysql/creation.py
shows this translation:
class DatabaseCreation(BaseDatabaseCreation):
# This dictionary maps Field objects to their associated MySQL column
# types, as strings. Column-type strings can contain format strings; they'll
# be interpolated against the values of Field.__dict__ before being output.
# If a column type is set to None, it won't be included in the output.
data_types = {
'AutoField': 'integer AUTO_INCREMENT',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
...
To change that, you should either monkey-patch this dict doing:
from django.db.backends.mysql.creation import DatabaseCreation
DatabaseCreation.data_types['AutoField'] = 'integer UNSIGNED AUTO_INCREMENT'
Or you create your own class, so you won't mess up with the other AutoFields
:
from django.db.models.fields import AutoField
class UnsignedAutoField(AutoField):
def get_internal_type(self):
return 'UnsignedAutoField'
from django.db.backends.mysql.creation import DatabaseCreation
DatabaseCreation.data_types['UnsignedAutoField'] = 'integer UNSIGNED AUTO_INCREMENT'
And then create your own PKs:
id = UnsignedAutoField()
As it descends from AutoField
, it will inherit all of its behavior.