Использование 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, не вызывая слишком больших проблем?
<ч/" > ^ Некоторые из причин: скрытие подсчетов объектов, предотвращение обхода идентификатора "идентификатор", использование нескольких серверов для создания неконфликтных объектов,...
Ответы
Ответ 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)