Reputation: 676
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
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
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