简体   繁体   English

Django - 如何根据属性的值对查询集进行排序

[英]Django - How to sort through a queryset based on the value of an attribute

I have created the following model which stores information for an html5 banner. 我创建了以下模型,用于存储html5横幅的信息。 I have a ForeignKey to associate the banner with a specific project. 我有一个ForeignKey将横幅与特定项目相关联。

class BannerCode(models.Model):
    ROUNDS_LIST = (
        ('1', '1'),
        ('2', '2'),
        ('3', '3'),
        ('4', '4'),
        ('5', '5'),
        ('6', '6'),
    )

    project = models.ForeignKey(Project)
    client = models.ForeignKey(Client, null=True, blank=True)
    name = models.CharField(max_length=256, null=True, blank=True)
    width = models.CharField(max_length=3, null=True, blank=True)
    height = models.CharField(max_length=3, null=True, blank=True)
    review_round = models.CharField(max_length=3, choices=ROUNDS_LIST, default=1)

I need to print out in my template something like this desired Output: 我需要在我的模板中打印出类似所需的输出:

Round 1 第1轮

  • banner name 横幅名称
  • banner name 横幅名称
  • banner name 横幅名称
  • banner name 横幅名称

Round 2 第2轮

  • banner name 横幅名称
  • banner name 横幅名称
  • banner name 横幅名称
  • banner name 横幅名称

I am having trouble understanding how to loop through the objects and sort by the review_round attribute. 我无法理解如何遍历对象并按照review_round属性进行排序。

I created a custom filter and am able to sort them in one long list: 我创建了一个自定义过滤器,并能够在一个长列表中对它们进行排序:

@register.filter
def sort_by(queryset, order):
    return queryset.order_by(order)

In Template: 在模板中:

{% for b in project.bannercode_set.all|sort_by:'review_round' %}
    {{ b.review_round }}
{% endfor %}

This loop works great for outputting something like this: 这个循环非常适合输出这样的东西:

Current Output 电流输出

  • banner name, round 1 横幅名称,第1轮
  • banner name, round 1 横幅名称,第1轮
  • banner name, round 2 横幅名称,第2轮
  • banner name, round 3 横幅名称,第3轮

How can I create a for loop that would match my desired output? 如何创建一个与我想要的输出匹配的for循环?

In your view: 在你看来:

banners = BannerCode.objects.all().order_by('review_round') 

***if you want to reverse order use '-review_round' ***如果你想逆转订单,请使用'-review_round'

Then in your template: 然后在你的模板中:

{% for item in banners %}

    <li>{{ item.name }}</li>

{% endfor %}

您更改{{ b.review_round }}在你的模板{{ b.name }}

In this scenario you're either going to have to have different sections in your template for the different review rounds, or define the context for your template differently to render the headers. 在这种情况下,您要么必须在模板中有不同的部分用于不同的审核轮次,要么以不同的方式定义模板的上下文以呈现标题。

Here's an example which defines the variable review_round_groups to hold our template context. 这是一个定义变量review_round_groups来保存模板上下文的示例。 review_round_groups is a dictionary which maps the header of each section to the queryset it should render (in this case each queryset is the result of filtering on a different round_review): review_round_groups是一个字典,它将每个部分的标题映射到它应该呈现的查询集(在这种情况下,每个查询集都是对不同的round_review进行过滤的结果):

review_round_groups = {}

for review_round_int in BannerCode.ROUNDS_LIST:  # Group BannerCode's into review rounds
    review_round_int = review_round_int[0]  # Value to filter on
    review_round_groups['Round %d' % review_round_int] = BannerCode.objects.filter(review_round=review_round_int)

Then in your template: 然后在你的模板中:

{% for banner_group_name, banner_qs in review_round_group.items %}
    <h1>{{ banner_group_name }}</h1>
    {% if banner_qs.exists %}
        <ul>
        {% for banner in banner_qs %}
            <li>{{ banner.name }}</li>
        {% endfor %}
        </ul>
    {% endif %}
{% endfor %}

This should render all your different review rounds as unordered lists, if there are no banners for a certain review_round then it will not display that group. 这应该将所有不同的审核轮次呈现为无序列表,如果某个review_round没有横幅,则它将不会显示该组。 If you want to still render the header for an empty review round group, just remove the {% if banner_qs.exists %} . 如果您仍想呈现空审核轮组的标头,只需删除{% if banner_qs.exists %}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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