26

Is it possible to make a ForeignKey to more than one model? I want to choose from different models like Parts and Machines Model.

I read this to combine multiple models into one list: How to combine multiple querysets in Django?

How can I get the foreign key to that list?

4 Answers 4

29

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?

Sign up to request clarification or add additional context in comments.

2 Comments

Unfortunately, with this method and how it implements GenericForeignKey, you can't use the database API so it was a non-starter for my particular use case.
How can you not use the API with that?
11

You need generic relations.

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

3 Comments

would you mind explaining how this will work with my example?
I might have been unclear. I want to be able to choose from multiple objects from different models. So its a combination of parts and machines. So in the dropdown list i would have ex: Drilling machine, Press, 1.5mm angle iron, 1v switch etc etc
This link is dead
3

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

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.