[Django]-GenericForeignKey or ForeignKey

4👍

There is no generic answer to this, just considerations. The decision depends on the business logic you need to implement with this solution.

Two Columns

order.discount = ForeignKey(Discount, null=True)
order.social_discount = ForeignKey(SocialDiscount, null=True)

When checking in subsequent code:

if order.discount:
    # do this based on Discount model
elif order.social_discount:
    # do that based on SocialDiscount model

This is a solution in favor of two very different Discount behaviours.

Use this:

  • if there are only those two and no more in the future,
  • if you would call very different fields and methods on them (they have different business logic surrounding them).

Non-Abstract Parent

# renamed from AbstractDiscount to ParentDiscount for obvious reasons
order.discount = ForeignKey(ParentDiscount, null=True)

Subsequent code:

if order.discount:
    # do things that apply to either discount
    if isinstance(order.discount, 'Discount'):
        # do things that only apply to Discount
    elif isinstance(order.discount, 'SocialDiscount'):
        # do things that only apply to SocialDiscount

Use this:

  • if there might be more children of ParentDiscount in the future,
  • if there is general business logic that applies to any type of ParentDiscount that would be shared between all children.

GenericForeignKey

Querying on GenericForeignKeys requires a bit of work. As @Andy remarked it is not directly supported, but you can of course query on content_type and object_id together. The __in lookup won’t work unless you can rely on object_id only.

It won’t work out of the box in forms. For the Django Admin, there might be some solution, though, see GenericForeignKey and Admin in Django.

Use this:

  • if there might be more discounts of various types in the future (ask the product owner and make sure this is not just some far far away future),
  • if there is general business logic that applies to any those types,
  • if you don’t need a no-work quick Admin solution.

Leave a comment