Автоматическое поле не уменьшает длину столбца

#python #django #django-models #python-3.9 #django-3.2

Вопрос:

Я пытаюсь создать поле автоматического приращения для крошечного целого числа, такого как int(3).

Если я попытаюсь AutoField , он создаст длину 11. Если я использую max_length , миграция игнорирует это.

SmallIntegerField дает int(6) без автоматического приращения.

Мое определение модели:

 class tblroles(models.Model):
    role_id = SmallIntegerField(primary_key=True, verbose_name="role_id")
    name = CharField(max_length=20)
    is_active = BooleanField(default=False)
 

Комментарии:

1. Какой сервер базы данных вы используете?

2. Я использую mysql.

Ответ №1:

У Джанго нет tinyint поля. Но вы можете создать пользовательское автоматически увеличивающееся автоматическое поле, переопределив db_type(...) метод как

 from django.db.models import SmallAutoField


class TinyAutoField(SmallAutoField):

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

Использование

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

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

PS: Это решение отлично работает в MySQL 8.0

Ответ №2:

SmallIntegerField является smallint (максимальное значение со знаком 32767 , ширина отображения 6 ) в MySQL.

Я полагаю, вы хотите tinyint (максимальное значение со знаком 127 , ширина отображения 3 ) в 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)
 

Использование:

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

Но если вам нужен литерал int(3) (максимальное значение со знаком 2147483647 , ширина отображения 3 ) в 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
 

Использование:

 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)