Django model to relate with "container" of another model multiple objects
Sorry for weird topic naming but trying to find out the best way to create model relation with some kind of objects set. Lets say I have some models:
class Furniture(models.Model):
title = models.CharField()
category = models.ForeignKey(Category)
price = models.PositiveIntegerField()
class Plumbing(models.Model):
title = models.CharField()
....
class Part(models.Model):
title = models.CharField()
code = models.CharField()
I want to build relations of every Furniture / Plumbing
instances with some set of Part
instances (like fittings, screws, etc.). The first most obvious approach is to create ManyToMany
field in Furniture
and Plumbing
models. But wondering if there is another approach to create some kind of "container" to have all the objects related together. As we know - there is no one-to-many
field in Django and I don't want to keep planty null
fields in Part
if I decide to make relations for many other models (not only Furniture
and Plumbing
).
I know that models archutecture is weid since it's a legacy code but any suggestions are welcome.
You can create a "container" model that links the Furniture, Plumbing, and Part models through a many-to-many relationship. For example:
class ItemContainer(models.Model):
name = models.CharField(max_length=100)
class Furniture(models.Model):
title = models.CharField(max_length=100)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
price = models.PositiveIntegerField()
containers = models.ManyToManyField(ItemContainer)
class Plumbing(models.Model):
title = models.CharField(max_length=100)
containers = models.ManyToManyField(ItemContainer)
class Part(models.Model):
title = models.CharField(max_length=100)
code = models.CharField(max_length=50)
containers = models.ManyToManyField(ItemContainer)
in this structure, you create an ItemContainer model that acts as a container for Furniture, Plumbing, and Part. Each item type can link to multiple containers, and the containers can hold related parts. This avoids adding null fields and allows flexibility for future relationships.
You might get this done by using a combination of "Container" model and GenericRelations
.
Since any instance of Furniture
or Plumbing
can have a 0 - many corresponding parts. You can achieve this by creating a M2M realtionship between Part
and Container
. Then to link to either Furniture
or Plumbing
you can use a GenericRelation
from django.db import models
from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Part(models.Model):
title = models.CharField(max_length=255)
code = models.CharField(max_length=50)
class Container(models.Model):
parts = models.ManyToManyField(Part, related_name="containers")
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
class Furniture(models.Model):
title = models.CharField(max_length=255)
category = models.ForeignKey("Category", on_delete=models.CASCADE)
price = models.PositiveIntegerField()
container = GenericRelation(Container)
class Plumbing(models.Model):
title = models.CharField(max_length=255)
container = GenericRelation(Container)
# ========================================
# Usage example
furniture = Furniture.objects.last()
furniture_parts = furniture.container.first().parts.all()
plumbing = Plumbing.objects.last()
plumbing_parts = plumbing.container.first().parts.all()