20

It is 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 2 or more querysets in a Django view?

How can I get foreign key to that list somehow?

shafik
  • 5,554
  • 5
  • 33
  • 45
Harry
  • 12,005
  • 27
  • 100
  • 164

3 Answers3

26

I know that you asked this over 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
  • 373
  • 3
  • 8
9

You need generic relations.

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

ygesher
  • 1,113
  • 11
  • 25
Daniel Roseman
  • 567,968
  • 59
  • 825
  • 842
  • would you mind explaining how this will work with my example? – Harry Jan 26 '11 at 12:32
  • 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 – Harry Jan 26 '11 at 12:33
  • This link is dead – ygesher Sep 20 '16 at 05:40
0

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
  • 350
  • 4
  • 11