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()
Вернуться на верх