【问题标题】:Writing on-request filtering for related objects为相关对象编写请求过滤
【发布时间】:2021-11-21 05:18:40
【问题描述】:

假设我们有以下模型

class Category(models.Model):
    name = models.CharField(max_length=254)

class Item(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="items")
    name = models.CharField(max_length=254)
    state = models.ForeignKey(State, on_delete=models.CASCADE)

类别和它们的项目是这样列出的

def view(request):
   categories = Category.objects.all()
   pass

{% for category in categories %}
    {{ category.name }}
    {% for item in category.items.all %}
        {{ item.name }}
    {% endfor %}
{% endfor %}
 

在这个结构中,我想为列出的“项目”编写请求过滤。

def view(request):
    ...
    queryset = ???
    state = request.GET.get('state')
    if state:
        queryset = queryset.filter(state__name=state)

问题在于定义“查询集”。因为,项目被列为类别的相关对象。

可以正确完成吗?还是我需要改变设计?

你可以看看我的设计更清楚。

Low fidelity design

【问题讨论】:

    标签: django django-models django-views django-templates django-queryset


    【解决方案1】:

    您在类别字段的项目对象中的related_name 应命名为“项目”。然后 category.items.all 将为您提供该类别中的项目列表。看documentation中的例子。

    class Tag(models.Model):
        article = models.ForeignKey(
            Article,
            on_delete=models.CASCADE,
            related_name="tags",
        )
        name = models.CharField(max_length=255)
    

    要根据类别过滤项目,您可以在请求中传递类别的 PK 并根据这些特定类别进行过滤。

    views.py
    def your_view(request):
        ...
        list_of_your_category_ids = [1,4] #get them as a list from frontend
        list_of_your_state_names = [1,2] 
        queryset =  Item.objects.filter(
                    category__in=list_of_your_category_ids,
                    state__code__in=list_of_your_category_names
                )
    

    这将为您提供所需的查询集。现在你需要的只是用它们的类别重新组合这个查询集。

    Django 提供了一个regroup 模板标签来做这个。

    {% regroup queryset by category as categories_list %}
    <ul>
        {% for category in categories_list %}
        <li>
            {{category.grouper}}
            <ul>            
                {% for item in category.list %}
                <li>
                    {{item}}: state - {{item.state.code}}
                </li>
                {% endfor %}
            </ul>
        </li>
        {% endfor %} 
    </ul>
    https://i.stack.imgur.com/TbTpz.png
    

    【讨论】:

    • 感谢您的回复。我在编写示例代码时犯了一个错误。但是,在代码中,我们已经假设 category.items.all 有效。问题是为这些项目编写请求过滤。您是否可以重新考虑您的回复?
    • 确保我理解问题所在。您想要做的是,给定一个类别,假设 PK = 1 的类别,您想要获取此给定类别中的所有项目。对吗?
    • 假设我们正在列出类别及其项目。正如我在代码中提到的那样,这没有问题。但是我想为列出的项目编写动态过滤器。实际上,如果您再看一下我的问题,就会清楚得多。
    • 编辑了我的答案。这是你想做的吗?
    • 非常感谢您为帮助我所做的努力。有一种结构,多个类别将位于同一部分。所以,我认为该解决方案不适合我。我在我的问题中添加了我的低保真设计。你能检查一下吗?
    猜你喜欢
    • 2010-09-20
    • 2019-02-14
    • 2018-11-18
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    相关资源
    最近更新 更多