Как отсортировать данные с предварительным заказом обработки по глубине из модели django в python?

#python #django #django-models

#python #django #django-модели

Вопрос:

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

 [{
    'id': 27, 
    'has_sub_topic': 1, 
    'name': '123123', 
    'xml_name': '123123',
    'validated': 1, 
    'created_at': '2021-12-02 02:19:44.962043', 
    'updated_at': '2021-12-02 02:19:44.962043', 
    'last_editor_id': 2,
    'parent_id': None, 
    'subject_module_level_id': 25, 
    'order': 1
}, {
    'id': 34, 
    'has_sub_topic': 0, 
    'name': 'nosub', 
    'xml_name': 'nosub',
    'validated': 1, 
    'created_at': '2021-12-02 02:19:44.962043', 
    'updated_at': '2021-12-02 02:19:44.962043', 
    'last_editor_id': 2,
    'parent_id': None, 
    'subject_module_level_id': 25, 
    'order': 2
}, {
    'id': 31, 
    'has_sub_topic': 1, 
    'name': 'asdasda', 
    'xml_name': 'asdasda',
    'validated': 1, 
    'created_at': '2021-12-02 02:19:44.962043', 
    'updated_at': '2021-12-02 02:19:44.962043', 
    'last_editor_id': 2,
    'parent_id': None, 
    'subject_module_level_id': 25, 
    'order': 3
}, {
    'id': 28, 
    'has_sub_topic': 0, 
    'name': '11111', 
    'xml_name': '11111',
    'validated': 1, 
    'created_at': '2021-12-02 02:19:44.962043', 
    'updated_at': '2021-12-02 02:19:44.962043', 
    'last_editor_id': 2,
    'parent_id': 27, 
    'subject_module_level_id': 25, 
    'order': 1
}, {
    'id': 29, 
    'has_sub_topic': 0, 
    'name': '2222', 
    'xml_name': '2222',
    'validated': 1, 
    'created_at': '2021-12-02 02:19:44.962043', 
    'updated_at': '2021-12-02 02:19:44.962043', 
    'last_editor_id': 2,
    'parent_id': 27, 
    'subject_module_level_id': 25, 
    'order': 2
}, {
    'id': 32, 
    'has_sub_topic': 0, 
    'name': 'qweqwe', 
    'xml_name': 'qweqwe',
    'validated': 1, 
    'created_at': '2021-12-02 02:19:44.962043', 
    'updated_at': '2021-12-02 02:19:44.962043', 
    'last_editor_id': 2,
    'parent_id': 31, 
    'subject_module_level_id': 25, 
    'order': 1
}, {
    'id': 33, 
    'has_sub_topic': 0, 
    'name': 'zxczxcz', 
    'xml_name': 'zxczxcz',
    'validated': 1, 
    'created_at': '2021-12-02 02:19:44.962043', 
    'updated_at': '2021-12-02 02:19:44.962043', 
    'last_editor_id': 2,
    'parent_id': 31, 
    'subject_module_level_id': 25, 
    'order': 2
}] 

Я получаю данные, используя модель django с помощью этого кода:

 topics = Topics.objects.order_by('order', 'parent') 

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

 [
  {
    'id': 27,
    'has_sub_topic': 1,
    'name': '123123',
    'xml_name': '123123',
    'validated': 1,
    'created_at': '2021-12-02 02:19:44.962043',
    'updated_at': '2021-12-02 02:19:44.962043',
    'last_editor_id': 2,
    'parent_id': None,
    'subject_module_level_id': 25,
    'order': 1
  },
  {
    'id': 28,
    'has_sub_topic': 0,
    'name': '11111',
    'xml_name': '11111',
    'validated': 1,
    'created_at': '2021-12-02 02:19:44.962043',
    'updated_at': '2021-12-02 02:19:44.962043',
    'last_editor_id': 2,
    'parent_id': 27,
    'subject_module_level_id': 25,
    'order': 1
  },
  {
    'id': 29,
    'has_sub_topic': 0,
    'name': '2222',
    'xml_name': '2222',
    'validated': 1,
    'created_at': '2021-12-02 02:19:44.962043',
    'updated_at': '2021-12-02 02:19:44.962043',
    'last_editor_id': 2,
    'parent_id': 27,
    'subject_module_level_id': 25,
    'order': 2
  },
  {
    'id': 34,
    'has_sub_topic': 0,
    'name': 'nosub',
    'xml_name': 'nosub',
    'validated': 1,
    'created_at': '2021-12-02 02:19:44.962043',
    'updated_at': '2021-12-02 02:19:44.962043',
    'last_editor_id': 2,
    'parent_id': None,
    'subject_module_level_id': 25,
    'order': 2
  },
  {
    'id': 31,
    'has_sub_topic': 1,
    'name': 'asdasda',
    'xml_name': 'asdasda',
    'validated': 1,
    'created_at': '2021-12-02 02:19:44.962043',
    'updated_at': '2021-12-02 02:19:44.962043',
    'last_editor_id': 2,
    'parent_id': None,
    'subject_module_level_id': 25,
    'order': 3
  },
  {
    'id': 32,
    'has_sub_topic': 0,
    'name': 'qweqwe',
    'xml_name': 'qweqwe',
    'validated': 1,
    'created_at': '2021-12-02 02:19:44.962043',
    'updated_at': '2021-12-02 02:19:44.962043',
    'last_editor_id': 2,
    'parent_id': 31,
    'subject_module_level_id': 25,
    'order': 1
  },
  {
    'id': 33,
    'has_sub_topic': 0,
    'name': 'zxczxcz',
    'xml_name': 'zxczxcz',
    'validated': 1,
    'created_at': '2021-12-02 02:19:44.962043',
    'updated_at': '2021-12-02 02:19:44.962043',
    'last_editor_id': 2,
    'parent_id': 31,
    'subject_module_level_id': 25,
    'order': 2
  }
] 

Я пробовал этот код, он работает с данными json, но он не работает, когда я получаю данные непосредственно с помощью модели django из базы данных.

 topics_ordered = []
for topic in topics_test:
            if topic.has_sub_topic or not topic.parent_id:
                topics_ordered.append(topic)
                for topic_sub in topics_test:
                    if topic_sub.parent_id == topic.id:
                        topics_ordered.append(topic_sub) 

Когда я получаю данные непосредственно с помощью модели django из базы данных, он получает только родительские данные следующим образом:

 [
  {
    'id': 27,
    'has_sub_topic': True,
    'name': '123123',
    'xml_name': '123123',
    'parent_id': None,
    'order': 1
  },
  {
    'id': 34,
    'has_sub_topic': False,
    'name': 'nosub',
    'xml_name': 'nosub',
    'parent_id': None,
    'order': 2
  },
  {
    'id': 31,
    'has_sub_topic': True,
    'name': 'asdasda',
    'xml_name': 'asdasda',
    'parent_id': None,
    'order': 3
  }
] 

Кто-нибудь знает, как решить эту проблему без преобразования данных в json?

Комментарии:

1. Не совсем уверен, что понимаю, чего вы пытаетесь достичь здесь, но topic.parent , похоже, это отношение FK, поэтому if topic_sub.parent == topic.id: , скорее всего, никогда не будет оцениваться как true, поскольку вы сравниваете объект темы с int. Вы можете либо изменить topic.id на topic или topic_sub.parent на topic_sub.parent.id

2. Сначала вы должны были реализовать структуру базы данных, подобную MPTT, чтобы легко получить элементы в древовидном порядке. Или используйте что-то вроде django-mptt для упрощения операций с деревом.

3. Я просто хочу сначала отсортировать данные от родительского и его дочерних элементов по порядку, а затем следующего родительского элемента и его дочерних элементов. topic.parent — это отношение FK к самим темам. Я попытался изменить topic_sub.parent на topic_sub.parent.id и я получил эту ошибку: объект ‘NoneType’ не имеет атрибута ‘id’

Ответ №1:

Я думаю, что этот код решит проблему, но этот подход недостаточно хорош.

 topics = sorted(topics, key=lambda d: d.parent.order if d.parent else d.order)