# Generic relation vs Many to Many

**URL:** <https://forum.djangoproject.com/t/generic-relation-vs-many-to-many/16967>\
**Category:** Using the ORM\
**Created:** [November 12, 2022, 2:21am UTC](https://forum.djangoproject.com/t/generic-relation-vs-many-to-many/16967 "2022-11-12T02:21:15Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![shawnngtq](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/shawnngtq/32/5834_2.png) [@shawnngtq](https://forum.djangoproject.com/u/shawnngtq)\
**Post date:** [November 12, 2022, 2:21am UTC](https://forum.djangoproject.com/t/generic-relation-vs-many-to-many/16967/1 "2022-11-12T02:21:15Z")

</div>

## When should we use Generic relation or ManytoMany relation?

## Standard foreign key

```python
class Object1(models.Model):
    ...

class Object1Task(models.Model):
    object1 = models.ForeignKey(Object1)
    ...

class Object20(models.Model):
    ...

class Object20Task(models.Model):
    object20 = models.ForeignKey(Object20)

```

If you have many class (`Object1` to `Object20`) that have similar table (`Object1Task` to `Object20Task`) that contains exact fields. **It’s not DRY**.

## Generic relation

```python
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

class Task(models.Model):
    content_type = models.ForeignKey(
        ContentType,
        null=True,
        on_delete=models.SET_NULL,
        related_name="task",
    )
    object_id = models.PositiveBigIntegerField(
        blank=True,
        null=True,
    )
    content_object = GenericForeignKey(
        "content_type",
        "object_id",
    )
    ...

```

By using Generic relation, we don’t need to create `Object1Task` to `Object20Task`, just `Task` table is fine. **It is DRY and create fewer database tables than foreign key & manytomany approach, but the issue is that querying is not easy, we need to use `GenericRelation`**.

## ManytoMany

```python
class Task(models.Model):
    object1 = models.ManyToManyField(object1)
    ...
    object20 = models.ManyToManyField(object20)

```

If we use `ManyToManyField`, **it’s DRY and easier to query than generic relation**.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [November 12, 2022, 3:35am UTC](https://forum.djangoproject.com/t/generic-relation-vs-many-to-many/16967/2 "2022-11-12T03:35:30Z")

</div>

There are actually three choices when faced with this type of situation.

- You can recognize that database integrity is more important than the principle of DRY, and create the straight-forward code and models.

- You can recognize that database integrity is important, give up some clarity in your code, and use some not-so-obvious metaprogramming with your models to kinda maintain DRY.

- You can believe that DRY is more important than the integrity of your data, and rely upon generic relations and Generic Foreign Keys (GFK).

(Note: I’m not going to address the potential performance implications of any of these options here. Performance-related issues are highly context-sensitive, and the _real_ implications of these types of situations can only be evaluated in the context of the live deployment.)

`<opinion>`  
Mentally, I put generic relations into the same category as signals. Frequently, they’re recommended and used in areas where they don’t belong or aren’t needed.

Yes, GFKs can be useful - but not in as many situations as people may think.

Yes, GFKs are sometimes even necessary.

But I would never refactor code to create GFKs, regardless of the amount of code that might be removed.

Our approach is always to consider a GFK as the “solution of last resort.” Our principle for schema design is more like “how can we avoid using a GFK here?” rather than “let’s use a GFK to make this easier.” (And yes, sometimes the answer _is_ to use a GFK.)  
`</opinion>`
