Использование UUID в качестве первичного ключа в моделях Django (влияние общих отношений)
по ряду причин^, я хотел бы использовать UUID в качестве первичного ключа в некоторых из моих моделей Django. Если я это сделаю, я все равно смогу использовать внешние приложения, такие как "contrib.комментарии", "Джанго-голосование" или "Джанго-тегов", которые используют родовых отношений через значение 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)
Это приложение, по-видимому, предполагает, что первичный ключ для голосуемой модели является целым числом.
в встроенное приложение для комментариев, похоже, способно обрабатывать нецелые PKs, хотя:
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")
является ли эта проблема "integer-PK-assumed" общей ситуацией для сторонних приложений, которые сделают использование UUIDs болью? Или, возможно, я неправильно понимаю эту ситуацию?
есть ли способ использовать UUIDs в качестве первичных ключей в Django, не вызывая слишком много проблем?
^ Некоторые из причин: скрытие подсчетов объектов, предотвращение обхода url-адреса "id", использование нескольких серверы для создания неконфликтных объектов, ...
3 ответа:
первичный ключ UUID вызовет проблемы не только с родовыми отношениями, но и с эффективностью в целом: каждый внешний ключ будет значительно дороже-как хранить, так и присоединять-чем машинное слово.
однако ничто не требует, чтобы UUID был первичным ключом: просто сделайте его среднее ключ, дополняя вашу модель с полем uuid с
unique=True
. Используйте неявный первичный ключ как обычный (внутренний для вашей системы) и используйте UUID в качестве своего внешний идентификатор.
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)
я столкнулся с подобной ситуацией и узнал в официальная документация Django, что
object_id
Не обязательно должен быть того же типа, что и primary_key соответствующие модели. Например, если вы хотите, чтобы ваши общие отношения были действительны для обоих IntegerField и страничке id, просто установите свойobject_id
быть страничке. Поскольку целые числа могут принудительно переходить в строки, все будет в порядке. То же самое касается 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)