문제

I am developing a hirerchical application where leaf nodes can be instances of different models. I can't figure out how to make it work with django-mptt app. Is this even possible in that application? If yes, what am I doing wrong? and if no, is there anything out there what does what I am trying to do?

The following is a basic structure of the models:

class FolderItemBase(MPTTModel):
    order = models.PositiveIntegerField()

    class Meta:
        abstract = True

    class MPTTMeta:
        parent_attr = 'folder'
        order_insertion_by = ['order']

class Folder(FolderItemBase):
    folder = TreeForeignKey('Folder', related_name='folders', blank=True, null=True)
    ...

class Image(FolderItemBase):
    folder = TreeForeignKey('Gallery', related_name='images') # cannot be null since leaf has to be inside of a folder
    ...

When I try to do the following I am only able to get the Folder children, and none of the images. Same thing when I try to get ancestors of the images

>>> folder1 = Folder.objects.create(title='Folder 1', order=0)
>>> folder2 = Folder(title='Folder 2', order=0)
>>> folder2.insert_at(folder1, save=True)
>>> image = Image(...)
>>> image.insert_at(folder1, save=True)
>>> folder1.get_children()
[<Folder: Folder 2>]
>>> image.get_ancestores()
[]

And this is how things are stored in the db after all of this:

Folder table
----------------
+----+-------+-----+------+---------+-------+-----------+----------+
| ID | order | lft | rght | tree_id | level | folder_id | title    |
+----+-------+-----+------+---------+-------+-----------+----------+
| 1  | 0     | 1   | 4    | 1       | 0     |           | Folder 1 |
+----+-------+-----+------+---------+-------+-----------+----------+
| 2  | 0     | 2   | 3    | 1       | 1     | 1         | Folder 2 |
+----+-------+-----+------+---------+-------+-----------+----------+

Images Table
------------
+----+-------+-----+------+---------+-------+-----------+
| ID | order | lft | rght | tree_id | level | folder_id |
+----+-------+-----+------+---------+-------+-----------+
| 1  | 1     | 2   | 3    | 1       | 1     | 1         |
+----+-------+-----+------+---------+-------+-----------+

As you can see it figures what should be the level number for the image and the correct (at at least it seems to be) left and right numbers however it does not update anything in the folder table so then when you try to do a query, nothing gets selected.

Any pointers are appreciated. Thank you.

도움이 되었습니까?

해결책

AFAIK, this is not possible; django-mptt piggy backs on Django's QuerySet, which will only ever work with one type of things. You can a use the contenttypes framework to associate the "real" item with something like FolderItem, which would only be used for the hierarchy, e.g.

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class FolderItem(MPTTModel):
    folder = TreeForeignKey('Folder', related_name='folders', blank=True, null=True
    order = models.PositiveIntegerField()
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    class Meta:
        abstract = True

    class MPTTMeta:
        parent_attr = 'folder'
        order_insertion_by = ['order']

Then, when you're using the django-mptt manager methods and such, you'll get back a queryset of FolderItems, and you can access the Folder/Image for each as you iterate over the set, through the generic foreign key.

However, be aware that this will likely be costly in terms of database queries, since each time you access a generic foreign key, a new query must be issued.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top