# Is a GenericForeignKey a compound key?

**URL:** <https://forum.djangoproject.com/t/is-a-genericforeignkey-a-compound-key/40909>\
**Category:** Getting Started\
**Created:** [May 13, 2025, 12:33pm UTC](https://forum.djangoproject.com/t/is-a-genericforeignkey-a-compound-key/40909 "2025-05-13T12:33:43Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![lennybrans](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/lennybrans/32/28494_2.png) [@lennybrans](https://forum.djangoproject.com/u/lennybrans)\
**Post date:** [May 13, 2025, 12:33pm UTC](https://forum.djangoproject.com/t/is-a-genericforeignkey-a-compound-key/40909/1 "2025-05-13T12:33:43Z")

</div>

I am trying to wrap my head around the usage of a GenericForeignKey, and I am looking for better understanding (or confirmation I am understanding it correctly).

**Context**  
I have three models: Enterprise, Establishment and Activity.  
One can quickly reason that Enterprise - Establishment are a one-to-many relation. Activities however, are bound to a specific Establishment, if a Establishment exists. If not, then to an Enterprise (that has only one establishment and thus is not mentioned in Establishment).

Quick example:  
Company A has one establishment that sells food, thus this activity entry with label “food” should have a ForeignKey to Enterprise.  
Company B has two branches/establishments, one sells tools, another sells wood. The activity labels in this case will have a ForeignKey to the Establishment, and not (directly) to the Enterprise.

With this in mind

```auto
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models

class Enterprise(models.Model):
    """An active enterprise."""
    enterprise_id = models.CharField(
        primary_key=True,
        max_length=14,
        help_text="Enterprise ID."
    )
    status = models.CharField(
        max_length=2,
        help_text="Status."
    )

class Establishment(models.Model):
    """A local establishment of an existing enterprise."""
    establishment_id = models.CharField(
        primary_key=True,
        max_length=14,
        help_text="Establishment ID"
    )
    enterprise_id = models.ForeignKey(
        Enterprise, on_delete=models.CASCADE
    )

```

```auto
class Activity(models.Model):
    """Description of activity."""
    limit = models.Q(app_label='api_nbb', model="enterprise") | models.Q(app_label='api_nbb', model="establishment")
    entity = models.ForeignKey(
        ContentType, 
        on_delete=models.CASCADE, 
        limit_choices_to=limit
    )
    object_id = models.CharField()
    content_object = GenericForeignKey("entity", "object_id")
    
    activity_tag = models.CharField(
        max_length=10,
        help_text="Short description for activity."
    )

```

Let us pretend I do:

```auto
try:
    x = Enterprise.objects.get(enterprise_id="1234")
except Enterprise.DoesNotExist:
    x = Establishment.objects.get(establishment_id="1234")

activity = Activity(content_object=x, activity_tag="wood")
activity.save()

```

To me it seems that:

- An activity does not actually refer, in the DB at least, to the instance/row in table Enterprise/Establishment, but is rather a compound key of a class instance of either Enterprise/Establishment, and said instances attribute, in this case the `activity_tag` valued `wood`.
- The `on_delete=models.CASCADE` is unnecessary, since it is not linked to an entry in tables Enterprise/Establishment but to the existence of the (Django) models Enterprise/Establishment under `django_content_type`.

Are both mine assumptions correct here?

And (I know open question but I don’t expect an explanation, rather a nudge or pointer) considering the context, is this a legitimate use of the GenericForeignKey or should I use another strategy when later, I want to identify all information of one Enterprise? (in which case, I’ll have to write a custom query for the activities, I assume).

Thank you for any help and I have to say, new to Django but already a fan!

---

<div class="post-metadata">

**Author:** ![frankwiles](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/frankwiles/32/386_2.png) [@frankwiles](https://forum.djangoproject.com/u/frankwiles)\
**Post date:** [May 13, 2025, 3:16pm UTC](https://forum.djangoproject.com/t/is-a-genericforeignkey-a-compound-key/40909/2 "2025-05-13T15:16:49Z")

</div>

A GFK allows you to essentially ForeignKey your `Activity` model to ANY model in your Django project. User, Group, Site, anything…

It is not a database level foreign key constraint and you’re correct it’s just two fields that can be resolved to pointed to `object_id` of table `whatever`.

Personaly, I would restructure this data model a bit. I would have a `Many2Many` field on Establishment to Activity. This way you have a single “Food” or “Sells Tools” across all Establishments and then what an “Enterprise” has is imply the aggregation of all Activities across all an Enterprise’s Establishments.

---

<div class="post-metadata">

**Author:** ![lennybrans](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/lennybrans/32/28494_2.png) [@lennybrans](https://forum.djangoproject.com/u/lennybrans)\
**Post date:** [May 13, 2025, 3:56pm UTC](https://forum.djangoproject.com/t/is-a-genericforeignkey-a-compound-key/40909/3 "2025-05-13T15:56:43Z")

</div>

I like that idea. And it would definitely be beneficial.

I haven’t actually used a GFK in my code yet, that is, to get information rather than storing it. But my assumption is that it works like a regular FK once it is loaded into Django’s framework?
