Django-mptt использует get_root() для элемента TreeQuerySet внутри цикла for, и выходные данные, сохраненные в списке, не сохраняются за пределами цикла for
Я пытаюсь использовать get_root() для отдельных элементов TreeQuerySet в цикле for. Кажется, это работает в оболочке Django Python, как показано ниже. При двойном нажатии [Enter] для обозначения окончания цикла for результат применения get_root() к каждому элементу автоматически выводится на экран командной строки. Результат верен в том смысле, что в выходных данных действительно указан корень верхнего уровня каждого элемента TreeQuerySet.
Однако вне цикла список, в котором они должны храниться, не обновляется. Вместо этого этот список содержит исходные элементы TreeQuerySet.
In Django Python shell:
>>> topics_w_arttype_articles = topics.Topic.objects.filter(to_ArtTypeArticle_topic_from_Topic__title__isnull=False).distinct()
>>> topics_w_arttype_articles
<TreeQuerySet [<Topic: Level1Topic1>, <Topic: Level1Topic2>, <Topic: Level1Topic3>, <Topic: Level1Topic4>, <Topic: Level2Topic1>, <Topic: Level2Topic2>, <Topic: Level2Topic3>, <Topic: Level2Topic4>]>
>>> arttype_topic_roots_list = []
>>> for item in topics_w_arttype_articles.iterator():
... item.get_root()
... arttype_topic_roots_list.append(item)
...
<Topic: Level0Topic1>
<Topic: Level0Topic2>
<Topic: Level0Topic2>
<Topic: Level0Topic3>
<Topic: Level0Topic4>
<Topic: Level0Topic5>
<Topic: Level0Topic5>
<Topic: Level0Topic5>
>>> arttype_topic_roots_list
[<Topic: Level1Topic1>, <Topic: Level1Topic2>, <Topic: Level1Topic3>, <Topic: Level1Topic4>, <Topic: Level2Topic1>, <Topic: Level2Topic2>, <Topic: Level2Topic3>, <Topic: Level2Topic4>]
>>>
Я поместил логику взаимодействия с оболочкой в пользовательский тег шаблона, показанный ниже (с дополнительным кодом, который должен удалять дубликаты из списка, если они сохранялись вне цикла), чтобы предоставить список шаблонам. При использовании в шаблоне элементами являются исходные элементы TreeQuerySet, а не корневые узлы, созданные в цикле for. В чем проблема?
@register.simple_tag
def get_topic_roots_warticles():
topics_w_arttype_articles = topics.Topic.objects.filter(to_ArtTypeArticle_topic_from_Topic__title__isnull=False).distinct()
#topics_w_arttype_articles_list = list(topics_w_arttype_articles)
arttype_topic_roots_list = []
for item in topics_w_arttype_articles:
item.get_root()
arttype_topic_roots_list.append(item)
arttype_topic_roots_list_unique = []
for val in arttype_topic_roots_list:
if val not in arttype_topic_roots_list_unique:
arttype_topic_roots_list_unique.append(val)
return arttype_topic_roots_list_unique
В случае, если это имеет значение, соответствующая модель статьи выглядит следующим образом:
class ArtTypeArticle(articles.models.Article):
topic = TreeManyToManyField(
Topic,
related_name = 'to_ArtTypeArticle_topic_from_Topic',
blank=True,
)
def __str__(self):
"""
String for representing the Model object.
"""
return self.title # defined in articles.models.Article
И тема модели MPTT такова:
class Topic(MPTTModel):
name = models.CharField(max_length=100)
parent = TreeForeignKey(
'self',
related_name='return_to_Topic_parent_from_self',
on_delete=models.SET_NULL,
null=True,
blank=True)
description = models.TextField(
max_length=1000,
default='',
null=True,
blank=True)
class MPTTMeta:
order_insertion_by = ['name']
class Meta:
verbose_name = 'Topic'
verbose_name_plural = 'Topics'
def __str__(self):
return self.name
def get_first_ancestor(self):
if (self.level >= 1):
topic_object_first_ancestor = self.get_ancestors(ascending=True, include_self=False)[0]
return topic_object_first_ancestor
def get_second_ancestor(self):
if (self.level >=2):
topic_object_second_ancestor = self.get_ancestors(ascending=True, include_self=False)[1]
return topic_object_second_ancestor
def get_all_descendants(self):
topic_object_all_descendants = self.get_descendants(include_self=False)
return topic_object_all_descendants
Я пробовал заменить TreeQuerySet в списке на list() и использовать этот список в качестве элементов в цикле for. Это не имеет никакого значения.
Я также пробовал заменить item.get_root() на item.first().get_root, но это приводит к ошибке, подобной "first не является атрибутом объекта".
Я ожидал, что в оболочке >>> arttype_topic_roots_list будет создан список категорий Level0, как внутри цикла for, т.е.
<Topic: Level0Topic1>
<Topic: Level0Topic2>
<Topic: Level0Topic2>
<Topic: Level0Topic3>
<Topic: Level0Topic4>
<Topic: Level0Topic5>
<Topic: Level0Topic5>
<Topic: Level0Topic5>
а не:
>>> arttype_topic_roots_list
[<Topic: Level1Topic1>, <Topic: Level1Topic2>, <Topic: Level1Topic3>, <Topic: Level1Topic4>, <Topic: Level2Topic1>, <Topic: Level2Topic2>, <Topic: Level2Topic3>, <Topic: Level2Topic4>]
В шаблоне я ожидал, что будут доступны корни верхнего уровня, а не исходные элементы TreeQuerySet.