0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Django (>=3.2) で UUID を pk にしたい

Last updated at Posted at 2022-11-04

現時点 (django = "4.1.3") でのメモ

既定のPK指定

Customizing type of auto-created primary keysAutomatic primary key fields にある通り、デフォルトのPKを修正するには

  • settings.pyDEFAULT_AUTO_FIELD
settings.py

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
  • AppConfig.default_auto_field
apps.py
from django.apps import AppConfig


class HogeConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'hoge'

のどちらかを変更すればいいが、これは AutoField のサブクラス(4.1実装では AutoFieldMixin を実装してるクラス)の

  • AutoField
  • BigAutoField
  • SmallField

以外を指定すると怒られる。

❯ python manage.py migrate
<snip>
ValueError: Primary key 'django.db.models.UUIDField' referred by DEFAULT_AUTO_FIELD must subclass AutoField.

django/db/models/fields/__init__.py
class AutoField(AutoFieldMixin, IntegerField, metaclass=AutoFieldMeta):
    def get_internal_type(self):
        return "AutoField"

    def rel_db_type(self, connection):
        return IntegerField().db_type(connection=connection)


class BigAutoField(AutoFieldMixin, BigIntegerField):
    def get_internal_type(self):
        return "BigAutoField"

    def rel_db_type(self, connection):
        return BigIntegerField().db_type(connection=connection)


class SmallAutoField(AutoFieldMixin, SmallIntegerField):
    def get_internal_type(self):
        return "SmallAutoField"

    def rel_db_type(self, connection):
        return SmallIntegerField().db_type(connection=connection)

なので、Cloud Spannerなどの要件でPKをUUIDに指定する時は、必ず各 models に id フィールドとして指定しなければならない。

UUIDFieldの型

models.UUIDField は、PostgreSQL以外では最長32文字のchar扱い。

class UUIDField(Field):
    default_error_messages = {
        "invalid": _("“%(value)s” is not a valid UUID."),
    }
    description = _("Universally unique identifier")
    empty_strings_allowed = False

    def __init__(self, verbose_name=None, **kwargs):
        kwargs["max_length"] = 32
        super().__init__(verbose_name, **kwargs)

これはリファレンスにも明記されている。

なので、MySQLやMariaDBで扱う場合は36文字じゃ無いことを意識しておくと良い。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?