Search code examples
djangodjango-modelsdjango-contenttypes

Is it possible to use contenttype with non primary key for the object?


I would to use non-primary key in the content type object as the following :

My content type model:

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

with my other model as :

class Task(models.Model):
    uid=uid = models.UUIDField(default=uuid.uuid4, unique=True)
    title = models.CharField(_('Title'), max_length=128, help_text=_('Title'))
    votes = GenericRelation(Vote)

Now, the schema get create, I am able to create objects, but not to retrieve: the following doesn't work :

t = Task.objects.create(title='task1')
t.votes.all()

I get the following error :

django.db.utils.ProgrammingError: operator does not exist: uuid = integer
LINE 1: ..."content_type_id" = 19 AND "vote"."object_uid" = 16) ORDE...

Now I do understand this error, and I understand that its trying to evaluate an integer against an uuid. Is there a way to indicate django that it should use the uid field instead of the pk ?


Solution

  • Short answer: No, it is not possible to make GenericForeignKey use any other target field than the primary key. The primary key is hard-coded in GenericForeignKey, GenericRelation, and a number of supporting classes (inlines, related descriptors, that kind of thing).

    If you really want to use a UUID as the target field, then you'll have to set the UUID field as the primary key on your target model, and use a type compatible with UUIDs as Vote.object_id (such as a CharField, or even a TextField – that way you'll still be able to point to models with an integer primary key, too).