Django - Models - Linking models to another and vice versa

I am trying to link venues to the products they supply. The products supplied are not unique to each venue.

As a result, Venue 1 and 2 could both provide Product A.

The outcome I am looking for is twofold:

  1. when a Product is added to the database, there is an option to link it to an existing Venue
  2. When looking at a venue in particular, I would like to have the list of all the product that can be supplied

I tried using Foreign Keys and ManyToManyFields but this only seems to add all the products available to the database to all the venues without leaving a choice.

The second problem is obviously referring to Product from the Venue model. If I input a foreign key or any form of relation in it, Django gets upset and tells me Product is not defined.

I thought of creating a 3rd model, that could combine both Venue and Products, but it feels like there must be something more sophisticated that could done.

class Venue(models.Model):
    name = models.CharField(verbose_name="Name",max_length=100, null=True, blank=True)
   
class Product(models.Model):
    name = models.CharField('Product Name', max_length=120, null=True)
    venue = models.ForeignKey(Venue, blank=True, related_name="venue", on_delete=models.CASCADE)
    

A ManyToManyField should in fact be perfect for what you want to do. It only associates those objects to one another for which relations have been explicitly created, e.g. in the admin or programmatically. I'm not sure what behavior you currently get, but maybe the documentation page on the topic clarifies it for you. You can define your ManyToManyField either on Product or on Venue.

But first regarding your second problem: The argument related_name works differently than you apparently think: In your last line of code, you should rather write something like related_name="available_products", because related_name becomes the name of an attribute of your Venue instances, by which you can then access all Product objects that have been associated to that Venue object, e.g. like so: venue.available_products.all()

related_name works the same for ManyToManyField and ForeignKey, so all in all, you should do something like:

class Venue(models.Model):
    name = models.CharField(verbose_name="Name",max_length=100, blank=True)

class Product(models.Model):
    name = models.CharField('Product Name', max_length=120, blank=True)
    venues = models.ManyToManyField(Venue, blank=True, related_name="available_products")

(Side note: For CharFields, it is recommended not to set null=True and instead only use blank=True, because otherwise there would be two different options for "no data", namely Null and an empy string. Details in the docs.)

Back to Top