【问题标题】:Django template : display objects in cascade with foreign keyDjango模板:使用外键级联显示对象
【发布时间】:2018-09-20 14:38:27
【问题描述】:

我正在尝试在我的模板中显示一些由Foreign Key field 连接的 django 对象。

我试着做一个简单的例子来说明我想用accordion html在我的模板中得到什么。

我的 django 模型:

class Grandparent(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)

    def __str__(self):
        return f"{self.name} : {self.age}"


class Parent(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)
    grandparent = models.ForeignKey(Grandparent, related_name='grandparent')

    def __str__(self):
        return f"{self.name} : {self.age}"


class Child(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)
    parent = models.ForeignKey(Parent, related_name='parent')

    def __str__(self):
        return f"{self.name} : {self.age}"

如您所见,孩子依赖于父母,而父母又依赖于祖父母。

我的 html 模板:

现在我想在我的 HTML 模板中显示类似的内容:

所以我的 HTML 如下所示,我没有克服得到我想要的东西:

{% for grandparent in grandparent_list %}
<div class="accordion-publication panel-group" id="accordion" role="tablist" aria-multiselectable="true">
  <div class="panel-primary">
    <div class="panel-heading" role="button" id="head_0" data-toggle="collapse">
      <span>{{ grandparent }}</span>
    </div>
    {% for parent in parent_list %}
    <div class="panel-collapse collapse in" role="tabpanel" aria-expanded="true">
      <div class="panel-body">
        <div class="panel panel-default">
          <div class="panel-heading collapsed" role="button" data-toggle="collapse" aria-expanded="true">
            <span class="panel-title">{{ parent }}</span>
          </div>
          <div class="panel-collapse collapse in" role="tabpanel" aria-labelledby="head_0">
            <div class="panel-body">
            {% for child in child_list %}
              <table class="table table-condensed">
                <tbody>
                  <tr>
                    <td class="col-md-1"> {{ child }}</td>
                  </tr>
                </tbody>
              </table>
            {% endfor %}
            </div>
          </div>
        </div>
      </div>
    </div>
    {% endfor %}
  </div>
</div>
{% endfor %}

这个HTML有点通用,但我没有克服为了显示for each grandparent显示each parents associated然后显示each child associated to each parent..

我的 django 视图:

我的 django 视图中的类如下所示:

def get_context_data(self, **kwargs):

    self.count_number_document()
    self.flag_publication()
    kwargs['child_list'] = Child.objects.all().order_by('parent__grandparent__name')
    kwargs['parent_list'] = Parent.objects.all().order_by('name')
    kwargs['grandparent_list'] = Grandparent.objects.all()

    return super(MyClassView, self).get_context_data(**kwargs)

【问题讨论】:

  • 您的相关名称没有意义。 related_name for Parent.grandparent 用于获取相关的父母,因此最好使用related_name='parents'。同样,最好将related_name='children 用于Child.parent
  • @Alasdair 好的,你是对的,但我认为我的主要问题是关于我的模板中的get_context_data 方法和for loop?在这部分我暂时被阻止了。即使我会用你的评论纠正我的模型。
  • @Alasdair 我找到了答案!我将回答我的问题并使其成为解决方案。非常感谢您,因为您对related_name 的评论让我得到答案:)

标签: django django-models django-templates


【解决方案1】:

感谢 Alasdair 的回答,我找到了解决方案。

首先,我必须像这样定义我的模型(related_nameadjustement):

class Grandparent(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)

    def __str__(self):
        return f"{self.name} : {self.age}"


class Parent(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)
    grandparent = models.ForeignKey(Grandparent, related_name='parents')

    def __str__(self):
        return f"{self.name} : {self.age}"


class Child(models.Model):
    name = models.CharField(...)
    age = models.IntegerField(...)
    parent = models.ForeignKey(Parent, related_name='children')

    def __str__(self):
        return f"{self.name} : {self.age}"

然后,在我的 view.py 文件中,我只需要设置:

kwargs['grandparent_list'] = Grandparent.objects.all().order_by('name')

最后在我的 html 模板中:

{% for grandparent in grandparent_list %}
<div class="accordion-publication panel-group" id="accordion" role="tablist" aria-multiselectable="true">
  <div class="panel-primary">
    <div class="panel-heading" role="button" id="head_0" data-toggle="collapse">
      <span>{{ grandparent }}</span>
    </div>
    {% for parent in grandparent.parents.all %}
    <div class="panel-collapse collapse in" role="tabpanel" aria-expanded="true">
      <div class="panel-body">
        <div class="panel panel-default">
          <div class="panel-heading collapsed" role="button" data-toggle="collapse" aria-expanded="true">
            <span class="panel-title">{{ parent }}</span>
          </div>
          <div class="panel-collapse collapse in" role="tabpanel" aria-labelledby="head_0">
            <div class="panel-body">
            {% for child in parent.children.all %}
              <table class="table table-condensed">
                <tbody>
                  <tr>
                    <td class="col-md-1"> {{ child }}</td>
                  </tr>
                </tbody>
              </table>
            {% endfor %}
            </div>
          </div>
        </div>
      </div>
    </div>
    {% endfor %}
  </div>
</div>
{% endfor %}

【讨论】:

    【解决方案2】:

    首先,在所有相关名称上使用“children”,以便 grandparent.children.all() 将给出祖父母的所有孩子,即 Parent 实例。同样对于 Parent 和 Child 类也是如此。

    来到视图,只发送上下文中的祖父母。但是等等,如果你访问孩子和他们的孩子,这将导致 N+1 个查询。 所以在发送祖父母时使用预取。

    grandparents = Grandparent.objects.all().prefetch_related(Prefetch('children', queryset=Parent.objects.all().prefetch_related('children'))) 
    

    【讨论】:

      猜你喜欢
      • 2013-02-07
      • 2022-06-25
      • 2016-09-14
      • 2011-04-27
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 2021-11-17
      • 2021-08-28
      相关资源
      最近更新 更多