UUIDField vs Charfield с UUID в нем?

Итак, я использую UUID в поле CharField в качестве PK для многих вещей в проекте, над которым я работаю, все работает нормально, никаких проблем. Если я использую UUIDField, некоторые вещи в бэкенде будут иметь проблемы с UUID-полем (обычно это функции, которые ожидают, что UUID будет строкой).

Есть ли преимущество использования UUIDField по сравнению с просто 'default=uuid.uuid4' в CharField?

UUIDField - это, по сути, поле CharField длиной 32 символа, которое проверяет, что был предоставлен действительный UUID. Согласно документации, тип UUID будет сохранен в Postgres, но как CharField в любой другой БД.

https://docs.djangoproject.com/en/4.0/ref/models/fields/#uuidfield

Не понимаю, почему вы не можете просто использовать CharField с default=uuid.uuid4 (который в любом случае нужен для UUIDField), вы просто потеряете автоматическую валидацию.

Есть ли преимущество использования UUIDField по сравнению с просто default=uuid.uuid4 в CharField?

Да.

A UUIDField для базы данных будет использоваться UUID типа [postgresql-doc], это сохранит UUID в виде 128-битного количества, что более компактно, чем хранение в виде строки, для которой потребуется 32 байта или, соответственно, 256 бит (что занимает в два раза больше места).

Если вы будете использовать CharField(max_length=36, default=uuid.uuid4), вам даже потребуется использовать 36 символов, так как UUID по умолчанию для str добавляет тире между ними, а не только использует шестнадцатеричное значение, и таким образом добавляет дополнительные четыре символа для этих тире, которые по сути одинаковы, и таким образом тратит больше памяти.

Но кроме этого есть и другие преимущества. Действительно, он будет следить за тем, чтобы длина CharField составляла 32 символа, и что формат, если он передан как строка, действительно является UUID. Таким образом, он будет выполнять надлежащую проверку формата.

Он также может разобрать несколько форматов строки в один и тот же UUID. Например, {12345678-1234-5678-1234-567812345678}, 12345678123456781234567812345678 и urn:uuid:12345678-1234-5678-1234-567812345678 будут разобраны в одно и то же значение, этого не произойдет, если вы используете простое CharField, так как тогда он будет считать, что это разные строки. Если вы, таким образом, работаете с:

MyModel.objects.filter(pk='urn:uuid:12345678-1234-5678-1234-567812345678')

Он получит запись с этим UUID, даже если значение хранится в базе данных в другом формате.

Значения, которые он извлекает из базы данных, обернуты в тип UUID. Это "богаче", чем strинг, и позволит избежать ошибок. Например, добавление двух UUID не имеет смысла. Действительно:

>>> uuid4() + uuid4()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'UUID' and 'UUID'

тогда как для строк это приведет к конкатенации двух строк.

Кроме того, он работает с UUIDField [Django-doc] как поле формы, это делает более удобным подключить другой виджет к этому типу поля, и таким образом отрисовать форму по-другому.

Таким образом, он предоставляет больше контекста о том, какой тип данных он ожидает, и обычно лучший контекст означает, что модули, которые интроспектируют модель, могут, таким образом, сделать лучшую работу.

Вернуться на верх