我一直在靠墙试图使用Django ORM进行查询,我到处搜索但找不到答案。 这是我的模特。
class Decision(models.Model):
ACTION_CHOICES = [('include', _('Include')), ('exclude', _('Exclude'))]
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
date_taken = models.DateTimeField(_('date taken'), default=timezone.now)
action = models.CharField(max_length=7, choices=ACTION_CHOICES)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
project = models.ForeignKey('projects.Project', on_delete=models.CASCADE)
is_permanent = models.BooleanField(_('is permanent'), default=False)
我想查询的是对用户在项目中所做的每个content_object的最新永久性决策,因为在应用程序中重复调用此查询,迭代通过更简单的QuerySet(如Decision.filter(user_id=user.pk, project_id=project.pk)
)来获取最终结果不是一个选择。到目前为止,我使用像这样的RawQuerySet解决了它。
Decision.objects.raw("SELECT decision.id, decision.content_type_id, decision.object_id "
"FROM canvasblocks_decision AS decision "
"WHERE decision.date_taken = (SELECT max(last_decision.date_taken) "
" FROM canvasblocks_decision AS last_decision "
" WHERE last_decision.object_id = decision.object_id AND "
" last_decision.content_type_id = decision.content_type_id AND "
" last_decision.project_id = %s AND decision.user_id = %s) ",
[project.pk, user.pk])
但是我不喜欢这个解决方案,因为我失去了所有的Django ORM能力,因为我必须再次过滤这个查询来检查动作,这种力量会让它失去痛苦,因为我必须在子查询中将其转换为所有带来的复杂性。那么伙计们,你知道更好的方法吗?顺便说一下,我正在使用Django 1.9.4。提前谢谢。
答案 0 :(得分:0)
如果数据集很小,你可以进行多次传递,但这不是一个好主意。
有两个选项,具体取决于您使用的数据库。
1)您可以更改sql以使用rank或dense_rank函数来使查询更加简单。
select decision.id, decision.content_type_id, decision.object_id,
first_value (last_decision.date_taken)
over (partition by ecision.id, decision.content_type_id, decision.object_id
order by last_decision.date_taken desc
)
from canvasblocks_decision AS decision
...
2)你可以在注释中加入相同的逻辑,以获得排名。这样你就拥有了django对象提供的所有内容,并获得了这个额外的列。
from django.db.models.expressions import RawSQL
Decision.objects.filter().annotate(rank=RawSQL("RANK() OVER (partition by id, content_type, object_id
(ORDER BY date_taken DESC)", [])
)
...