Django模型:如何从父模型中访问子项?

时间:2015-12-26 05:28:03

标签: django django-models django-template-filters

我需要查询以下模型,所以我得到一个以下形式的输出,其中父母按字母顺序列出,然后他们的孩子也按字母顺序列在父母的下面。

aparent
 -aparentchild
 -bchild
 -zchild
  -achildchild
  -xchildchild
bparent
 -xchild
cparent
 -achild
 -schild


class Category(BaseTimeModel):
    name = models.CharField(max_length=NAME_FIELD, blank=False, null=False, unique=True, help_text=HELP_TEXT)
    level = models.IntegerField(blank=True, null=True)
    parent = models.ForeignKey("self", blank=True, null=True, related_name="parents")
    details = models.CharField(max_length=DETAIL_FIELD, blank=True, null=True)

    class Meta:
        verbose_name_plural = "Categories"
        permissions = (
            ("view_category", "Can view category"),
        )

一些样本数据如下。

    Name        Level  Parent
   Bleh          0     Null         
   Category A    0     Null
   Tshirts       0     Null
   tt shirts     1     Tshirts
   butt shirts   1     Tshirts
   v necked      2     tt shirts

0级是父级,1表示子级,2表示孙级,依此类推。

要通过名称获取父母,以下查询提供

Category.objects.filter(level=0).order_by("name") 

Bleh
Category A
Tshirts

我如何让孩子们接受?请提示或链接到文档。

更新:

我想,

  Bleh
   Category A
   Tshirts
    -butt shirts
    -tt shirts
     -v necked

并且,我通过在模型中设置属性

来访问子项
@property
def get_children(self):
    return self.parents.all().order_by("name")

并且,在模型的列表视图中,

{% for object in object_list %}
    {{ object }} 
   {% if object.get_children %}
       {% for obj in object.get_children %}
             {{ obj }}
              ....
               and so on for further deep children.....
       {% endfor %}
   {% endif %}
{% endfor %}

然而,这不是DRY。提示。

1 个答案:

答案 0 :(得分:1)

您可以尝试使用django-mptt,它是专为在Django中使用递归模型而设计的。

将您的模型ForeignKeyTreeForeignKey交换,例如:

class Category(MPTTModel, BaseTimeModel):
    name = models.CharField(max_length=NAME_FIELD, blank=False, null=False, unique=True, help_text=HELP_TEXT)
    level = models.IntegerField(blank=True, null=True)
    parent = models.TreeForeignKey("self", blank=True, null=True, related_name="children")
    details = models.CharField(max_length=DETAIL_FIELD, blank=True, null=True)

    class MPTTMeta:
        level_attr = 'level'

level_attr将包含层次结构中对象的级别,例如最高父母的0

以文档为例,您的模板看起来像这样:

{% load mptt_tags %}

<ul class="root">
{% recursetree nodes %}
    <li>
        {{ node.name }}
        {% if not node.is_leaf_node %}
            <ul class="children">
                {{ children }}
            </ul>
        {% endif %}
    </li>
{% endrecursetree %}
</ul>

有关详细信息,请参阅this tutorial,其示例与您自己的用例非常相似。