django m2m through models

Django -- Posted on Oct. 23, 2021

A Django model for a category system. This model defines two classes: Category and ChildCategory. Here's a brief explanation of each class and its fields:

  1. Category class:

    • name: A character field representing the name of the category. It is limited to 100 characters and must be unique.
    • children: A many-to-many relationship to the Category model through the ChildCategory model. It represents the child categories related to this category.

    Category also defines two Meta options:

    • default_related_name: This sets the default related name for the reverse relation from the ChildCategory model to this model. In this case, it will be 'categories'.
    • verbose_name and verbose_name_plural: These specify the human-readable names for the model in singular and plural forms, respectively.

    The class includes two methods:

    • __str__(self): This method returns a string representation of the category's name.
    • depth_level(self): This method calculates the depth level of the category in the category hierarchy. It does so by following the relationship from the current category to its child categories (and their child categories, and so on) until there are no more child categories. It returns the depth level as an integer.

    The breadcrumb(self) method is also present. However, there seems to be a small error in the code. The method references self.targets.all(), but there is no field named targets defined in the Category class. It's likely that you intended to reference the children field instead.

  2. ChildCategory class:

    • source: A foreign key representing the source category (parent category) of the relationship. It relates to the Category model and uses the on_delete=models.CASCADE option, which means that if a Category instance is deleted, all related ChildCategory instances will also be deleted.
    • target: A foreign key representing the target category (child category) of the relationship. It also relates to the Category model and uses the on_delete=models.CASCADE option for the same reason as the source field.

Overall, these models seem to define a hierarchical category system, where a Category instance can have child categories connected through the ChildCategory model. The depth_level method helps determine the depth of a category in the hierarchy, and the breadcrumb method seems to be intended to generate a breadcrumb trail for a category (parent categories leading to the current category). However, there's a minor issue with the breadcrumb method that needs to be addressed.

                from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=100, unique=True)
    children = models.ManyToManyField('self', through='ChildCategory', symmetrical=False, blank=True)

    class Meta:
        default_related_name = 'categories'
        verbose_name = 'category'
        verbose_name_plural = 'categories'

    def __str__(self):

    def depth_level(self):
        depth = 0
        data = self.targets.all()
        while data:
            for item in data:
                data = item.source.targets.all()
            depth += 1
        return depth

    def breadcrumb(self):
        items = set()
        data = self.targets.all()
        if self.depth_level == 0:
            return items
        for item in data:
            items.add('{} > {}'.format(item.source, self))
        return items

class ChildCategory(models.Model):
    source = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='sources')
    target = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='targets')

Related Posts