3

私は、リーフノードをさまざまなモデルのインスタンスにすることができる階層型アプリケーションを開発しています。django-mpttアプリで動作させる方法がわかりません。これはそのアプリケーションでも可能ですか?はいの場合、私は何を間違っていますか?いいえの場合、私がやろうとしていることは何かありますか?

モデルの基本構造は次のとおりです。

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
    ...

次のことを実行しようとすると、フォルダの子のみを取得でき、画像は取得できません。画像の祖先を取得しようとすると同じこと

>>> 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()
[]

そして、これはすべての後に物事がデータベースに保存される方法です:

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         |
+----+-------+-----+------+---------+-------+-----------+

ご覧のとおり、画像のレベル番号と正しい(少なくともそう思われる)左右の番号がわかりますが、フォルダテーブルの内容は更新されないため、クエリを実行しようとすると、何も選択されません。

どんなポインタでも大歓迎です。ありがとうございました。

4

1 に答える 1

6

私の知る限り、これは不可能です。django-mpttDjango の にピギー バックします。DjangoQuerySetは 1 つのタイプのものでしか動作しません。contenttypes フレームワークを使用して、「実際の」アイテムを のようなものに関連付けることができますFolderItem。これは、階層にのみ使用されます。

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']

次に、django-mptt マネージャー メソッドなどを使用している場合、s のクエリセットが返され、汎用外部キーを使用して、セットを反復処理するときにそれぞれの/にFolderItemアクセスできます。FolderImage

ただし、一般的な外部キーにアクセスするたびに新しいクエリを発行する必要があるため、データベース クエリに関してはコストがかかる可能性があることに注意してください。

于 2012-06-20T14:43:55.150 に答える