djangodjango-models

Can I have an unsigned AutoField?


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?


Solution

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