Ограничение выбора древовидной структурой в сохраненной модели Django

У меня есть модель с родительским полем, которое ссылается на само себя, например, так:

parent = models.ForeignKey("self", null=True, blank = True )

Для корневого узла это поле будет пустым.

При создании нового экземпляра данных я хочу убедиться, что не добавляю экземпляр данных, который разрушает подразумеваемую структуру дерева. Например, если два экземпляра являются родителями друг друга.

Выборы для пользователя будут представлены через форму, поэтому мне нужно ограничить выбор, который будет представлен пользователю, сделав что-то вроде:

    class Meta:
        model = CategoryModel
        
    def __init__(self, *args, **kwargs):
        # Restrict choices so tree structure is not messed with
        self.fields['parent'].queryset = ???? 

Каким должен быть ?????

Я не совсем понял, что вы хотите от пользователей. Однако, если вы хотите создавать деревья с вашими объектами, то лучшим способом будет использование пакета Django-mptt, где у вас есть все возможности для создания объектов с parents, childs и nodes. Кроме того, наследуя его MPTTModel в вашей модели, наследуя в качестве результата поля для представления местоположения, такие как id дерева и какой родительский объект является id объекта.

Пример реализации:

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

# Create your models here.
class TestTree(MPTTModel):
    name = models.CharField(max_length=128)
    # Added after the creation of model, made - 
    # the migration and added data to the db.
    parent = TreeForeignKey(
        "self", on_delete=models.CASCADE, null=True, blank=True, related_name="children"
    )
    def __str__(self):
        return str(self.name)

    def save(self, *args, **kwargs):
        # script to rebuild the tree in case it is not organized. # <-------
        super(TestTree, self).save(*args, **kwargs)
        try:
            trees = TestTree.objects.all()
            for tree in trees:
                if tree.lft or tree.rght or tree.tree_id == 0:
                    TestTree.objects.rebuild()

        except Exception as e:
            print(e)
            pass

Пример создания дерева:

records = MyModel.objects.build_tree_nodes({
    'id': 7,
    'name': 'parent',
    'children': [
        {
            'id': 8,
            'parent_id': 7,
            'name': 'child',
            'children': [
                {
                    'id': 9,
                    'parent_id': 8,
                    'name': 'grandchild',
                }
            ]
        }
    ]
})

Обязательно, прочитайте эту часть, чтобы увеличить свои возможности по работе с деревьями с помощью этого пакета.

Вернуться на верх