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:
- when a
Product
is added to the database, there is an option to link it to an existingVenue
- 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 CharField
s, 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.)