对 Django 模板中的相关项目进行排序 [英] Sorting related items in a Django template

查看:27
本文介绍了对 Django 模板中的相关项目进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以对 DJango 模板中的一组相关项进行排序?

即:这段代码(为了清楚起见省略了 HTML 标签):

{% 用于 eventsCollection %} 中的事件{{ event.location }}{% 在 event.attendee_set.all %}{{参加者.名字}} {{参加者.姓氏}}{% 结束为 %}{% 结束为 %}

显示几乎正是我想要的.我唯一要更改的是我按姓氏排序的与会者列表.我试过这样说:

{% for event in events %}{{ event.location }}{% 代表 event.attendee_set.order_by__last_name %}{{参加者.名字}} {{参加者.姓氏}}{% 结束为 %}{% 结束为 %}

唉,上面的语法不起作用(它产生一个空列表),我想到的任何其他变体也不起作用(报告了很多语法错误,但没有乐趣).

在我看来,我当然可以生成某种排序的与会者列表数组,但这是一个丑陋且脆弱(我是否提到过丑陋)的解决方案.

不用说,但我还是要说,我已经仔细阅读了在线文档并搜索了 Stack Overflow 和 django-user 的档案,但没有找到任何有用的东西(啊,如果只有查询集是字典 dictsort会做这项工作,但不是,也不是)

================================================/p>

编辑以添加其他想法接受 Tawmas 的回答后.

<小时>

Tawmas 完全按照我提出的方式解决了这个问题——尽管解决方案不是我所期望的.结果我学到了一种有用的技术,它也可以用于其他情况.

Tom 的回答提出了一种我已经在我的 OP 中提到的方法,但暂时被拒绝为丑陋".

丑陋"是一种直觉反应,我想澄清一下它有什么问题.这样做时,我意识到这是一种丑陋的方法的原因是因为我对将查询集传递给要呈现的模板的想法感到困惑.如果我放宽这个要求,那么应该有一种不丑陋的方法.

我还没有尝试过这个,但假设视图代码不是传递查询集,而是遍历查询集,生成一个事件列表,然后用一个查询集装饰每个事件,用于相应的参与者,WAS 以所需的方式排序(或过滤,或其他).像这样:

eventCollection = []events = Event.object.[过滤和排序以品尝]对于事件中的事件:event.attendee_list = event.attendee_set.[过滤并按口味排序]eventCollection.append(事件)

现在模板变成:

{% for event in events %}{{ event.location }}{% 为 event.attendee_list 中的与会者%}{{参加者.名字}} {{参加者.姓氏}}{% 结束为 %}{% 结束为 %}

缺点是视图必须一次实现"所有事件,如果有大量事件,这可能是一个问题.当然可以添加分页,但这会使视图变得相当复杂.

好处是准备要显示的数据"代码在它所属的视图中,让模板专注于格式化视图提供的数据以供显示.这是正确的.

所以我的计划是对大表使用 Tawmas 的技术,对小表使用上述技术表格,大小的定义留给读者(咧嘴笑)

解决方案

您需要在与会者模型中指定顺序,如下所示.例如(假设您的模型类名为参加者):

class 参加者(models.Model):元类:ordering = ['last_name']

请参阅手册以获取更多参考.>

编辑.另一种解决方案是向事件模型添加一个属性,您可以从模板访问该属性:

class 事件(models.Model):# ...@财产def sorted_attendee_set(self):返回 self.attendee_set.order_by('last_name')

您可以根据需要定义更多这些...

Is it possible to sort a set of related items in a DJango template?

That is: this code (with HTML tags omitted for clarity):

{% for event in eventsCollection %}
   {{ event.location }}
   {% for attendee in event.attendee_set.all %}
     {{ attendee.first_name }} {{ attendee.last_name }}
   {% endfor %}
 {% endfor %}

displays almost exactly want I want. The only thing I want to change is I the list of attendees to be sorted by last name. I've tried saying something like this:

{% for event in events %}
   {{ event.location }}
   {% for attendee in event.attendee_set.order_by__last_name %}
     {{ attendee.first_name }} {{ attendee.last_name }}
   {% endfor %}
 {% endfor %}

Alas, the above syntax doesn't work (it produces an empty list) and neither does any other variation I have thought of (lot's of syntax errors reported, but no joy).

I could, of course, produce some kind of array of sorted attendee lists in my view, but that is an ugly and fragile (and did I mention ugly) solution.

Needless to say, but I'll say it anyway, I have perused the on-line docs and searched Stack Overflow and the archives of django-user without finding anything helpful (ah, if only a query set were a dictionary dictsort would do the job, but it's not and it doesn't)

==============================================

Edited to add additional thoughts after accepting Tawmas's answer.


Tawmas addressed the issue exactly as I presented it -- although the solution was not what I expected. As a result I learned a useful technique that can be used in other situations as well.

Tom's answer proposed an approach I had already mentioned in my OP and tentatively rejected as being "ugly".

The "ugly" was a gut reaction, and I wanted to clarify what was wrong with it. In doing so I realized that the reason it was an ugly approach was because I was hung up on the idea of passing a query set to the template to be rendered. If I relax that requirement, there is an un-ugly approach that should work.

I haven't tried this yet, but suppose that rather than passing the queryset, the view code iterated through the query set producing a list of Events, then decorated each Event with a query set for the corresponding attendees which WAS sorted (or filtered, or whatever) in the desired way. Something like so:

eventCollection = []   
events = Event.object.[filtered and sorted to taste]
for event in events:
   event.attendee_list = event.attendee_set.[filtered and sorted to taste]
   eventCollection.append(event)

Now the template becomes:

{% for event in events %}
   {{ event.location }}
   {% for attendee in event.attendee_list %}
     {{ attendee.first_name }} {{ attendee.last_name }}
   {% endfor %}
 {% endfor %}

The downside is the view has to "actualize" all of the events at once which could be a problem if there were large numbers of events. Of course one could add pagination, but that complicates the view considerably.

The upside is the "prepare the data to be displayed" code is in the view where it belongs letting the template focus on formatting the data provided by the view for display. This is right and proper.

So my plan is to use Tawmas' technique for large tables and the above technique for small tables, with the definition of large and small left to the reader (grin.)

解决方案

You need to specify the ordering in the attendee model, like this. For example (assuming your model class is named Attendee):

class Attendee(models.Model):
    class Meta:
        ordering = ['last_name']

See the manual for further reference.

EDIT. Another solution is to add a property to your Event model, that you can access from your template:

class Event(models.Model):
# ...
@property
def sorted_attendee_set(self):
    return self.attendee_set.order_by('last_name')

You could define more of these as you need them...

这篇关于对 Django 模板中的相关项目进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆