I have trouble writing a django data model which can link multiple objects of the same type back to a single data entry. Here’s are my current models:
class House(models.Model):
name = models.CharField(max_length=200, unique=True)
color = models.CharField(max_length=200, unique=True)
class Config(models.Model)
name = models.CharField(max_length=200)
nbr_houses = models.PositiveIntegerField()
houses = models.ManyToManyField(House) # this does not work, since I can only map a house once back to Config.
I wanna do the following (pseudo-code):
# define a new config and enforce that is should have houses.
$ a = Config(name = 'new_config', nbr_houses = 3)
# associate individual houses with this config
$ a.houses[0] = House(pk= 1)
# associate the same house a second time with this config
$ a.houses[1] = House(pk= 1)
# associate a third house to config.
$ a.houses[2] = House(pk= 2)
I create a new Config object new_config and say that this configuration should have 3 houses. My model should then automatically check and force me to link the correct number of houses back to Config. Additionally, a House might reference back twice to the same configuration.
I was thinking of writing Config the following way
class Config(models.Model)
name = models.CharField(max_length=200)
nbr_houses = models.PositiveIntegerField()
houses = models.ManyToManyField(House, related_name='house0')
houses1 = models.ManyToManyField(House, related_name='house1')
houses2 = models.ManyToManyField(House, related_name='house2')
houses3 = models.ManyToManyField(House, related_name='house3')
to basically reflect the maximum number of associations possible, but that’s kinda inflexible. What’s a better way of accomplishing this?
EDIT: Imagine the following use case:
You want to write a computer game where you can define a complexity of a scene. Each scene is saved into a Config. Per scene, I can place x many houses. Houses don’t differ, they are just templates. So a scene could be made of 10 red houses, 2 blue houses and 1 yellow house. So for each Config entry I want to able to associate a different amount of houses (objects). Maybe later there will also be horses 🙂 I hope you get the idea.
The question was updated to explain that you potentially want to associate some number of each house with the config. In order to do this in Django you need a new model, that Django calls a intermediate model. Like this:
and then in the
Configclass you declare aManyToManyFieldand assign the intermediate model to thethroughparameter:To add houses to a config you create new instances of the intermediate model:
After executing the above queries, the database will look something like this:
To find out how many houses of a particular type there are in a particular config, you query the intermediate table, either directly, or via either one of the models:
Original answer
(The original question did not make it clear that the many-to-many relation needed multiplicity, but I’m leaving the original answer in place in case it’s useful.)
Your original idea (that
housesshould be aManyToManyField) is the right idea. It’s just that in order to refer to theHouseclass before you define it, you need to pass the name of the class. See the Django documentation:It’s also bad idea to have a
nbr_housesfield because it could become incorrect if someone updates the many-to-many relation without also remembering to update thenbr_housesfield. You can usehouses.count()to get the number of related houses.So your
Configclass should look like this:And you can update the many-to-many relation using the RelatedManager interface: there are methods
add,create,remove,clear, or you can just assign to it: