Search code examples
python-3.xdjango

Is Django many to many really necessary?


I have been learning to use Django over the last year and Python is not my native programming language. Normally, when I want to create a many to many relationship, I would create 3 tables, one of which contained two foreign keys to each of the other two tables. For this reason, I find the Django manytomany field very unnatural. Does this many to many field create a third table in the database to store the relationship ? If this is the case, then using a many to many field will stop the class structure from directly representing the table structure.

What I am wondering is if there is a reason I should be using this manytomany field or could I get away with using 3 classes to represent a many to many relationship ?

Thanks

Mark


Solution

  • I would create 3 tables, one of which contained two foreign keys to each of the other two tables. For this reason, I find the Django manytomany field very unnatural.

    This is exactly what Django is doing behind the curtains. If you inspect the database, you will see a junction table [wiki]. Django simply does this in the background. It simply presents it to the foreground as a field. As you can see in the database Representation of the ManyToManyField [Django-doc]:

    Behind the scenes, Django creates an intermediary join table to represent the many-to-many relationship. By default, this table name is generated using the name of the many-to-many field and the name of the table for the model that contains it. Since some databases don't support table names above a certain length, these table names will be automatically truncated and a uniqueness hash will be used, e.g. author_books_9cdf. You can manually provide the name of the join table using the db_table option.

    You can even add extra fields to this junction table, by defining the model in between explicitly, and specify this in the through=… parameter [Django-doc]. For example:

    class Category(models.Model):
        name = models.CharField(
            max_length=128,
            unique=True
        )
    
    class Item(models.Model):
        name = models.CharField(
            max_length=128,
            unique=True
        )
        categories = models.ManyToManyField(
            Category,
            through='ItemCategory'
            related_name='items'
        )
    
    class ItemCategory(models.Model):
        category = models.ForeignKey(Category, on_delete=models.CASCADE)
        item = models.ForeignKey(Item, on_delete=models.CASCADE)
        validated = models.BooleanField(default=False)

    A ManyToManyField is thus more a concept to make representing and querying more convenient.