Search code examples
djangodjango-mptt

django-mptt - How to set different models in the same tree


I would like to have a tree that would mimic a file system with folders and files. Folders and files would be defined by different models with different fields attributes.

models:

from mptt.models import MPTTModel, TreeForeignKey

class Folder(MPTTModel):
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
    name = models.CharField(max_length=50)
    type = models.CharField(max_length=50)

class File(MPTTModel):
    parent= TreeForeignKey(Document)
    filename = models.CharField(max_length=255)
    encoding = models.CharField(max_length=20)
    date_created = models.DateTimeField(auto_now_add=True)
    date_updated = models.DateTimeField(auto_now=True)

Creating some folders and files:

 from shapefile.models import Folder, File
 root = Folder.objects.create(name="Root")
 download = Folder.objects.create(name="Download", parent=root)
 upload = Folder.objects.create(name="Upload", parent=root)
 File.objects.create(filename="Test", encoding="UTF-8", parent=download)

Shoul have:

> Root
> --Download
> ----Test
> --Upload

How can I retrieve this tree in view and template?

Edit:

Files are not inserted as folder's nodes:

file = File.objects.get(filename="Test")
file.get_ancestors()
>>> []

Solution

  • You can combine the MPTTModel with a generic relation from the contenttypes framework. You can enable it by adding 'django.contrib.contenttypes' to your INSTALLED_APPS setting.

    from django.db import models
    from mptt.models import MPTTModel, TreeForeignKey
    
    class TreeItem(MPTTModel):
        content_type = models.ForeignKey(ContentType)
        object_id = models.PositiveIntegerField()
        content_object = GenericForeignKey('content_type', 'object_id')
        parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
    
    class Folder(models.Model):
        name = models.CharField(max_length=50)
        type = models.CharField(max_length=50)
    
    class File(models.Model):
        filename = models.CharField(max_length=255)
        encoding = models.CharField(max_length=20)
        date_created = models.DateTimeField(auto_now_add=True)
        date_updated = models.DateTimeField(auto_now=True)
    

    The mptt documentacion explains how to access the tree in your templates.