Ivan Rostovsky
Ivan Rostovsky

Reputation: 676

Django GenericForeignKey vs set of ForeignKey

I would like to discuss the case of using GenericRelation and GenericForeignKey.

I have the 2 models, Appartement and Mission. And I need to create LockCode model which will be connected to Appartment or Mission. I have added the GenericForeignKey to the LockCode and GenericRelation to the Appartement and Mission:

class LockCode(TimeStampedModel):
    context_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    context_id = models.PositiveIntegerField()
    context = GenericForeignKey('context_type', 'context_id')


class Mission(DirtyFieldsMixin, models.Model):
    lock_codes = GenericRelation(
        LockCode,
        content_type_field='context_type',
        object_id_field='context_id',
        related_query_name='mission'
    )

class Appartment(DirtyFieldsMixin, models.Model):
    lock_codes = GenericRelation(
        LockCode,
        content_type_field='context_type',
        object_id_field='context_id',
        related_query_name='appartment'
    )

It works ok. But added the complexity level to compare with adding 2 ForeignKeys, for appartement and for mission.

class LockCode(TimeStampedModel):
  appartement = models.ForeignKey(Appartement, null=True, blank=True)
  mission = models.ForeignKey(Mission, null=True, blank=True)

So should I keep the GFK or use 2 simple FK?

Upvotes: 0

Views: 1122

Answers (2)

Daniel Roseman
Daniel Roseman

Reputation: 599796

The complexity does not all happen in the field definitions. It also happens at query time: given a LockCode, how do you identify whether it belongs to an apartment or mission? With two foreign keys, you would need to check both each time and catch any exceptions.

If you never need to follow the relationship that way, then yes the GFK is unnecessary and two FKs would be better.

Upvotes: 1

voodoo-burger
voodoo-burger

Reputation: 2153

If you go with the second option, you will have to build in logic to make sure either appartement or mission is not null. If you were to ever add more such foreign key fields, this logic would become increasingly complex.

If you are sure you are never going to add more foreign keys and you don't mind the overhead of ensuring one of them is not null then you can go ahead and use the foreign keys, but for scalability I would stick with generic relations.

Upvotes: 1

Related Questions