1

I am trying to create auto increment field for tiny integer like int(3).

If I try AutoField, it generates length of 11. If I use max_length, migration ignores it.

SmallIntegerField gives int(6) without auto increment.

My model definition:

class tblroles(models.Model):
    role_id = SmallIntegerField(primary_key=True, verbose_name="role_id")
    name = CharField(max_length=20)
    is_active = BooleanField(default=False)
aaron
  • 39,695
  • 6
  • 46
  • 102
Abcdef
  • 43
  • 7

2 Answers2

2

Django doesn't come with a tinyint field. But, you can create a custom auto-incrementing auto-field by overriding the db_type(...) method as

from django.db.models import SmallAutoField


class TinyAutoField(SmallAutoField):

    def db_type(self, connection):
        return "tinyint AUTO_INCREMENT"

Usage

class FooBar(models.Model):
    id = TinyAutoField(
        primary_key=True,
    )

    def __str__(self):
        return f"{self.id}"

PS: This solution is perfectly working in MySQL 8.0

JPG
  • 82,442
  • 19
  • 127
  • 206
1

SmallIntegerField is smallint (maximum signed value 32767, display width 6) in MySQL.

I suppose you want tinyint (maximum signed value 127, display width 3) in MySQL.

class TinyAutoField(models.SmallAutoField):

    def db_type(self, connection):
        if connection.vendor == 'mysql':
            return 'tinyint AUTO_INCREMENT'
        return super().db_type(connection)

    def rel_db_type(self, connection):
        if connection.vendor == 'mysql':
            return 'tinyint'
        return super().db_type(connection)

Usage:

class tblroles(models.Model):
    # role_id = SmallIntegerField(primary_key=True, verbose_name="role_id")  # Change this
    role_id = TinyAutoField(primary_key=True, verbose_name="role_id")        # to this
    # ...

But if you want literal int(3) (maximum signed value 2147483647, display width 3) in MySQL.

class AutoField(models.AutoField):

    def __init__(self, *args, **kwargs):
        self.display_width = kwargs.pop('display_width', None)
        super().__init__(*args, **kwargs)

    def db_type(self, connection):
        if connection.vendor == 'mysql' and self.display_width:
            return 'int(%s) AUTO_INCREMENT' % self.display_width
        return super().db_type(connection)

    def deconstruct(self):
        name, path, args, kwargs = super().deconstruct()
        if self.display_width:
            kwargs['display_width'] = self.display_width
        return name, path, args, kwargs

Usage:

class tblroles(models.Model):
    # role_id = SmallIntegerField(primary_key=True, verbose_name="role_id")
    role_id = AutoField(primary_key=True, verbose_name="role_id", display_width=3)
aaron
  • 39,695
  • 6
  • 46
  • 102