Использование UUID в качестве первичного ключа в моделях Django (влияние общих отношений) - PullRequest
72 голосов
/ 14 октября 2010

По ряду причин ^ я хотел бы использовать UUID в качестве первичного ключа в некоторых моих моделях Django.Если я это сделаю, смогу ли я использовать внешние приложения, такие как "contrib.comments", "django-голосования" или "django-tagging", которые используют общие отношения через ContentType?

Использование "django-голосования"Например, модель голосования выглядит следующим образом:

class Vote(models.Model):
    user         = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType)
    object_id    = models.PositiveIntegerField()
    object       = generic.GenericForeignKey('content_type', 'object_id')
    vote         = models.SmallIntegerField(choices=SCORES)

Это приложение, по-видимому, предполагает, что первичным ключом для модели, по которой проводится голосование, является целое число.

Кажется, что встроенное приложение комментариев способно обрабатывать нецелые PK, хотя:

class BaseCommentAbstractModel(models.Model):
    content_type   = models.ForeignKey(ContentType,
            verbose_name=_('content type'),
            related_name="content_type_set_for_%(class)s")
    object_pk      = models.TextField(_('object ID'))
    content_object = generic.GenericForeignKey(ct_field="content_type", fk_field="object_pk")

Является ли эта проблема, предполагаемая "целочисленным PK", типичной ситуацией для третьих сторон?сторонние приложения, из-за которых использование UUID причиняет боль?Или, возможно, я неправильно понимаю эту ситуацию?

Есть ли способ использовать UUID в качестве первичных ключей в Django без особых проблем?

^ Некоторые из причин: сокрытие количества объектов, предотвращение «обхода идентификатора» по URL, использование нескольких серверов для создания неконфликтующих объектов, ...

Ответы [ 4 ]

177 голосов
/ 12 февраля 2015

Как видно из документации , из Django 1.8 есть встроенное поле UUID.Различия в производительности при использовании UUID против целого числа незначительны.

import uuid
from django.db import models

class MyUUIDModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

Вы также можете проверить этот ответ для получения дополнительной информации.

42 голосов
/ 15 октября 2010

Первичный ключ UUID вызовет проблемы не только с общими отношениями, но и с эффективностью в целом: каждый внешний ключ будет значительно дороже - и хранить, и присоединять - чем машинное слово.

Однако ничто не требует, чтобы UUID являлся первичным ключом: просто сделайте его вторичным ключом, добавив в вашу модель поле uuid с unique=True. Используйте неявный первичный ключ как обычно (внутренний для вашей системы) и используйте UUID в качестве внешнего идентификатора.

10 голосов
/ 27 мая 2016

Я столкнулся с подобной ситуацией и обнаружил в официальной документации Django , что object_id не обязательно должен быть того же типа, что и primary_key родственная модель. Например, если вы хотите, чтобы ваши родовые отношения были действительными для IntegerField и CharField идентификаторов, просто установите object_id на CharField . Поскольку целые числа могут приводить к строкам, все будет хорошо. То же самое касается UUIDField .

Пример:

class Vote(models.Model):
    user         = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType)
    object_id    = models.CharField(max_length=50) # <<-- This line was modified 
    object       = generic.GenericForeignKey('content_type', 'object_id')
    vote         = models.SmallIntegerField(choices=SCORES)
0 голосов
/ 05 января 2019

Вопрос можно перефразировать следующим образом: «Есть ли способ заставить Django использовать UUID для всех идентификаторов базы данных во всех таблицах вместо автоматически увеличиваемого целого числа?».

Конечно, я могу сделать:

id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

во всех моих таблицах, но я не могу найти способ сделать это для:

  1. Модули сторонних производителей
  2. Сгенерированные Django таблицы ManyToMany

Итак, похоже, это отсутствующая функция Django.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...