简体   繁体   中英

Django tree query spanning multi model relation

Please consider code the following code. I'd like to create something like a tree structure (it will be in a table) related to a specific loged-in user. I'd like to have an overviewpage in which all categories are shown for which this user has items in the subcategories. My query works, but gives me all subcategory records and all posible items in those subcategories (so not just the subset for which the user has records.

I have another way working by starting with the itemmodel and then going up in the tree, but thats not what i'm looking for (this makes creating a dynamic set of tables far to depended on the django template layer).

I've looked at select_related and prefetch, but I can't get close to a solution. Any help would be appriciated.

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

template:

< 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 %}

您应该能够使用类似这样的东西: Subcat.objects.filter(item_set__user=self.request.user).select_related('main_cat')

Finaly got to an answer to my question. For future reference:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM