django - foreign - uuid as primary key
Usar un UUID como clave principal en los modelos de Django(impacto de relaciones genéricas) (3)
Por una serie de razones ^, me gustaría utilizar un UUID como clave principal en algunos de mis modelos de Django. Si lo hago, ¿podré usar aplicaciones externas como "contrib.comments", "django-voting" o "django-tagging" que utilicen relaciones genéricas a través de ContentType?
Usando "django-voting" como ejemplo, el modelo de Voto se ve así:
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)
Esta aplicación parece estar asumiendo que la clave principal para el modelo que se vota es un número entero.
La aplicación de comentarios integrada parece ser capaz de manejar PK no enteros, sin embargo:
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")
¿Es este problema "entero-PK-supuesto" una situación común para aplicaciones de terceros que haría que usar UUID sea un problema? O, posiblemente, ¿estoy malinterpretando esta situación?
¿Hay alguna manera de usar UUID como claves principales en Django sin causar demasiados problemas?
^ Algunas de las razones: ocultar recuentos de objetos, prevenir url "id crawling", usar varios servidores para crear objetos no conflictivos, ...Django 1.8 ahora tiene un campo UUID incorporado. Las diferencias de rendimiento cuando se utiliza un UUID vs integer son insignificantes.
import uuid
from django.db import models
class MyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
Me encontré con una situación similar y descubrí en la documentación oficial de Django que el object_id
no tiene que ser del mismo tipo que la primary_key del modelo relacionado. Por ejemplo, si desea que su relación genérica sea válida para IntegerField y CharField id, simplemente configure su object_id
para que sea un CharField . Como los enteros pueden forzar en cadenas, estará bien. Lo mismo ocurre con UUIDField .
Ejemplo:
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)
Una clave primaria UUID causará problemas no solo con relaciones genéricas, sino con la eficiencia en general: cada clave externa será significativamente más costosa, tanto para almacenar como para unirse, que una palabra máquina.
Sin embargo, nada requiere que el UUID sea la clave principal: simplemente conviértalo en una clave secundaria , complementando su modelo con un campo uuid con unique=True
. Use la clave primaria implícita como normal (interna para su sistema) y use el UUID como su identificador externo.