Подтвердить что ты не робот

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

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

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

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")

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

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

<ч/" > ^ Некоторые из причин: скрытие подсчетов объектов, предотвращение обхода идентификатора "идентификатор", использование нескольких серверов для создания неконфликтных объектов,...

4b9b3361

Ответ 1

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

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

Ответ 2

Django 1.8 теперь имеет встроенное поле UUID. Различия в производительности при использовании UUID vs integer незначительны.

import uuid
from django.db import models

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

Ответ 3

Я столкнулся с подобной ситуацией и обнаружил в официальной документации 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)