Search code examples
djangotreedjango-mptt

Does django-mptt support nested models?


I have a database of nested entities, that actually address parts: Street-House-Technical Room. In other words, I'd like to have a tree of nodes with different attributes on each level.

What I'd like to implement is to use django-mptt features for this database, for example, I want to see the database as a tree in Django Admin.

I tried the following in my models.py:

from django.db import models
from mptt.models import MPTTModel, TreeForeignKey


class Street(MPTTModel):
    name = models.CharField(max_length=100)
    parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='streets')

    def __str__(self):
        return self.name


class House(MPTTModel):
    name = models.CharField(max_length=100)
    parent = TreeForeignKey(Street, on_delete=models.CASCADE, null=True, blank=True, related_name='houses')

    def __str__(self):
        return self.name


class TechRoom(MPTTModel):
    name = models.CharField(max_length=100)
    parent = TreeForeignKey(House, on_delete=models.CASCADE, null=True, blank=True, related_name='tech_rooms')

    def __str__(self):
        return self.name

and my admin.py looks as:

from django.contrib import admin
from mptt.admin import MPTTModelAdmin

from places.models import Street, House, TechRoom

admin.site.register(Street, MPTTModelAdmin)
admin.site.register(House, MPTTModelAdmin)
admin.site.register(TechRoom, MPTTModelAdmin)

The problem is it works as a regular Foreign key not as a tree. Is it possible to implement nested models using django-mptt? More specifically is it possible to use a model name (e.g. Street) instead of 'self' here:

parent = TreeForeignKey(Street, on_delete=models.CASCADE, null=True, blank=True, related_name='houses')


Solution

  • I found the required solution. It is the django-polymorphic-tree library. The author says:

    You can write Django models that form a tree structure where each node can be a different model type.

    And it works.