跨越多模型关系的Django树查询

时间:2018-02-12 16:53:10

标签: python django orm tree

请考虑以下代码代码。我想创建一个类似于特定的loged-in用户的树结构(它将在表格中)。我想要一个概述页面,其中显示了该用户在子类别中具有项目的所有类别。我的查询有效,但给了我所有子类别记录和这些子类别中的所有可用项目(所以不仅仅是用户有记录的子集。

我有另一种工作方式,从itemmodel开始,然后在树中,但这不是我正在寻找的(这使得创建一个动态的表集远远取决于django模板层)

我查看了select_related和prefetch,但我无法接近解决方案。任何帮助都会得到满足。

models.py:

from django.db import models
from model_utils.models import TimeStampedModel
from django.conf import settings


User = settings.AUTH_USER_MODEL

class MainCat(TimeStampedModel):
    name = models.CharField(max_length=100, unique=True)
    rank = models.IntegerField(default=10)
    icon_class = models.CharField(max_length=100, null=True, blank=True)


class SubCat(TimeStampedModel):
    name = models.CharField(max_length=100, null=False, blank=False)
    slug = models.SlugField(null=True, blank=True)
    icon_class = models.CharField(max_length=100, null=True, blank=True)
    main_cat = models.ForeignKey(MainCat)


class Item(TimeStampedModel):
    user = models.ForeignKey(User, blank=True, null=True)
    item_name = models.CharField(max_length=100, null=False, blank=False)
    sub_cat = models.ForeignKey(SubCat, blank=True, null=True)

views.py:

from django.views.generic import ListView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import MainCat

class MainCatByUserListView(LoginRequiredMixin, ListView):
    model = MainCat
    def get_queryset(self):
        qs = super(MainCatByUserListView, self).get_queryset()
        qs = qs.filter(subcat__item__user=self.request.user)
    return qs

模板:

< html >
< body >
{% for maincat in object_list %}
    < ul >
        <li> {{maincat.name}} </li>
        <ul>
        {% for subcat in maincat.subcat_set.all %}
            <li> {{subcat.name}} </li>
            {% for item in subcat.item_set.all %}
                <li> {{item.name}} </li>
            </ul>
        </ul>
        {% endfor %}
    {% endfor %}
{% endfor %}
< / body >
< / html >
{% endfor %}

2 个答案:

答案 0 :(得分:0)

您应该可以使用以下内容:Subcat.objects.filter(item_set__user=self.request.user).select_related('main_cat')

答案 1 :(得分:0)

最终得到了我的问题的答案。供将来参考:

class MainCatListView(LoginRequiredMixin, ListView):
    model = MainCat
    template_name = 'app/main_cat_overview.html'

    def get_queryset(self):
        qs = super(MainCatListView, self).get_queryset()
        qs_user_cat_set = SubCat.objects.filter(item__user=self.request.user).prefetch_related(Prefetch(
            "item_set",
        queryset=Item.objects.filter(user=self.request.user),
        to_attr="item_attr")
            ).distinct()
        qs = qs.filter(subcat__item__user=self.request.user).prefetch_related(Prefetch(
            "subcat_set",
            queryset=qs_user_subcat_set,
            to_attr="subcat_attr")
                ).distinct()
        return qs