ForeignKey формы ограничения в Джанго - PullRequest
4 голосов
/ 30 декабря 2008

Я использую Django для написания блогового приложения и пытаюсь реализовать иерархическую структуру категорий. У каждой категории есть «родительский» ForeignKey, указывающий на одну и ту же модель категории. Я хочу разрешить администраторам добавлять категории, и я хочу, чтобы интерфейс позволял им выбирать родительскую категорию категории. Тем не менее, я хочу избежать ситуаций, когда я - мой собственный дедушка, поэтому я хочу ограничить доступные варианты выбора категориями, которые не имеют рассматриваемой категории в качестве предка.

Прямо сейчас я контролирую это с точки зрения:

parent_candidates = list(Category.objects.all())
pruned_parent_list = [cat for cat in parent_candidates if instance.id not in cat.getHierarchy()]

где экземпляр - это редактируемая категория, а getHierarchy () - метод для получения списка идентификаторов предков.

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

Есть ли лучший способ сделать это? Я знаю, что могу добавить пользовательскую проверку на сервер, чтобы предотвратить это, но зачем давать пользователям возможность?

Ответы [ 5 ]

1 голос
/ 02 января 2009

Взгляните на приложение django-treebeard .

1 голос
/ 31 декабря 2008

Мне приходилось иметь дело с категориями произвольной глубины в SQL, и он, кажется, не очень подходит для хранения данных этого типа в нормальной форме, поскольку вложенные запросы и / или несколько объединений имеют тенденцию становиться уродливыми * быстро.

Это почти единственный случай, когда я бы выбрал какое-то неправильное решение, а именно - хранить категории в строковой форме, подкатегории, разделенные разделителем. Это делает и запросы к базе данных, и другие операции намного более тривиальными.

Таблица категорий будет выглядеть примерно так:

id    name
1     Internet
2     Internet/Google
3     Internet/Yahoo
4     Offline
5     Offline/MS Office/MS Excel
6     Offline/Openoffice

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

Как бы то ни было, иерархические данные в SQL сами по себе не являются тривиальными, поэтому, что бы вы ни делали, вам, вероятно, придется делать довольно пользовательское кодирование.

0 голосов
/ 30 декабря 2008

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

  • Интернет
    • Google
    • Yahoo
  • Offline
    • MS Office
    • OpenOffice

Обычно я справляюсь с этим так: у меня очевидно есть FK parent_id в таблице категорий. Для корневых элементов (Internet, Offline) parent_id будет равен 0. Итак, когда, по вашему мнению, вы пытаетесь получить «родительские категории» для выпадающего списка, вам необходимо решить, насколько далеко они могут продолжать вложение. Я в основном ограничиваюсь этим уровнем до первого уровня, поэтому, чтобы выбрать, какие категории показывать в раскрывающемся списке, вы должны сделать что-то вроде:

parents = Category.objects.filter(parent_id=0)

Теперь, очевидно, это несколько ограничивает подход, но вы можете увеличить уровень, который вы хотели бы включить, и разработать какую-то систему визуальной идентификации в вашем шаблоне для раскрывающегося списка (включая дополнительные пробелы или тире для каждого уровня в иерархия или что-то).

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

0 голосов
/ 30 декабря 2008

Я не уверен, что это лучше (по взаимодействию или иным образом), но ...

Вы можете проверить целостность иерархии при сохранении и при необходимости вызвать ошибку.

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

0 голосов
/ 30 декабря 2008

"Есть ли лучший способ сделать это?" На самом деле, нет. Иерархии сложны в реляционной модели. Ничто не облегчает, кроме полного отказа от SQL.

"записать механизм выбора в мой шаблон, просматривая pruned_parent_list для получения параметров" - вероятно, не оптимально Это должно произойти, по вашему мнению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...