[Django]-ForeignKey to multiple Models or Queryset

28πŸ‘

I know that you asked this over a year ago, but I had a similar problem and I want to share a link to the solution for future readers.

Generally the contenttypes framework solves this problem, and I guess this is what Daniel Roseman was talking about.

How to use dynamic foreignkey in Django?

πŸ‘€b3niup

10πŸ‘

You need generic relations.

A generic relation allows you to dynamically the target model of the foreign key.

2πŸ‘

I’ll provide a comprehensive answer for this question, I know its quite old, but it’s still relevant.

We’re gonna be using Generic Relations.

First, in settings.py make sure that django.contrib.contenttypes is included in the INSTALLED_APPS array.

Let’s create a new model in models.py:

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation

With content_type we can associate Image with any other model class, while object_id will hold the other model instance.

class Image(models.Model):
    image = models.ImageField(
      upload_to="imgs/products", blank=True)

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey()

To refer back to the Image model from a Company instance we need to make a reverse generic relation

class Company(models.Model):
  name = models.CharField(max_length=100)
  images = GenericRelation(Image)

In schema.py, we can create Images in a Company instance like:

company_instance = Company(name="Apple")
company_instance.save()
for img in imgs:
    #Image(image=img, content_object=company_instance)
    company_instance.images.create(image=img)
company_instance.images.all() # fetch all images

the company_instance.images field is just a GenericRelatedObjectManager (docs)

This is how the final Image table looks in the database:
image table

πŸ‘€ahmelq

0πŸ‘

The Django-polymorphic library provides a simple solution that should work well with the admin and forms too using formsets.

For example:

from polymorphic.models import PolymorphicModel


class BookOwner(PolymorphicModel):
    book = models.ForeignKey(Book, on_delete=models.CASCADE)

class StaffBookOwner(BookOwner):
    owner = models.ForeignKey(Staff, on_delete=models.CASCADE)

class StudentBookOwner(BookOwner):
    owner = models.ForeignKey(Student, on_delete=models.CASCADE)

With this, you can use the parent model to set the owner to either a Staff or Student instance or use the child models directly.

πŸ‘€Timon

Leave a comment