Django:通过多对多字段订购模型 [英] Django: Order a model by a many-to-many field

查看:166
本文介绍了Django:通过多对多字段订购模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个具有人物模型的Django应用程序,并且我遇到了一个障碍。我将角色对象分配给使用多对多关系的角色 - 角色具有名称和权重。我希望以最重的角色重新命令我的名单。如果我做People.objects.order_by(' - roles__weight'),那么当人们分配了多个角色时,我会得到重复的。

I am writing a Django application that has a model for People, and I have hit a snag. I am assigning Role objects to people using a Many-To-Many relationship - where Roles have a name and a weight. I wish to order my list of people by their heaviest role's weight. If I do People.objects.order_by('-roles__weight'), then I get duplicates when people have multiple roles assigned to them.

我的初始想法是添加一个称为最重的角色权重的非规范化字段,并按此排序。每次从用户添加或删除新角色时,都可以对其进行更新。但是,事实证明,每次在Django中更新ManyToManyField时,都无法执行自定义操作( yet ,无论如何)。

My initial idea was to add a denormalized field called heaviest-role-weight - and sort by that. This could then be updated every time a new role was added or removed from a user. However, it turns out that there is no way to perform a custom action every time a ManyToManyField is updated in Django (yet, anyway).

所以,我以为我可以完全超越,写一个自定义字段,描述符和管理器来处理这个 - 但这似乎是非常当ManyToManyField动态创建ManyRelatedManager时,很难。

So, I thought I could then go completely overboard and write a custom field, descriptor and manager to handle this - but that seems extremely difficult when the ManyRelatedManager is created dynamically for a ManyToManyField.

我一直在想出一些可以为我做的这个聪明的SQL - 我确信这是可能的有一个子查询(或几个),但是我会担心Django支持的所有数据库后台都不能兼容。

I have been trying to come up with some clever SQL that could do this for me - I'm sure it's possible with a subquery (or a few), but I'd be worried about it not being compatible will all the database backends Django supports.

有没有人这样做过 - 或有任何想法可以实现吗?

Has anyone done this before - or have any ideas how it could be achieved?

推荐答案

Django 1.1(目前的测试版)添加了聚合支持。您的查询可以通过以下方式完成:

Django 1.1 (currently beta) adds aggregation support. Your query can be done with something like:

from django.db.models import Max
People.objects.annotate(max_weight=Max('roles__weight')).order_by('-max_weight')

生成的查询是:

The generated query is:

$ c> SELECT people.id,people.name,MAX(role.weight)AS max_weight
FROM people LEFT OUTER JOIN people_roles ON(people.id = people_roles.people_id)
LEFT OUTER JOIN角色ON( people_roles.role_id = role.id)
GROUP BY people.id,people.name
ORDER BY max_weight DESC

SELECT people.id, people.name, MAX(role.weight) AS max_weight FROM people LEFT OUTER JOIN people_roles ON (people.id = people_roles.people_id) LEFT OUTER JOIN role ON (people_roles.role_id = role.id) GROUP BY people.id, people.name ORDER BY max_weight DESC

这篇关于Django:通过多对多字段订购模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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