如何通过 django 模型查询创建与组的左连接
Posted
技术标签:
【中文标题】如何通过 django 模型查询创建与组的左连接【英文标题】:How to create left join with group by django model query 【发布时间】:2015-05-07 18:12:39 【问题描述】:嗨,我声明了 django 模型如下,我只想通过查询运行简单的左连接。
mysql查询
SELECT u.name, COUNT('j.*') as num_jobs FROM `User` as u
LEFT JOIN Job as j ON u.id = j.userId_id GROUP BY j.userId_id
上面的查询是获取每个用户的工作计数。
Django 模型
from django.db import models
class Users(models.Model):
name = models.CharField(max_length=60,verbose_name="Name",null=True, blank=True)
email_id = models.CharField(max_length=60,verbose_name="Email Id",null=True, blank=True)
phonenumber = models.CharField(max_length=20, verbose_name="Phone Number")
class Meta:
verbose_name_plural = "Users"
verbose_name = "Users"
db_table = "User"
def __unicode__(self):
return str(self.phonenumber) + ": "+ str(self.name)
class Job(models.Model):
userId = models.ForeignKey(Users)
title = models.CharField(max_length=128,verbose_name="Title")
description = models.TextField(verbose_name="Description",null=True, blank=True)
class Meta:
verbose_name_plural = "Job"
verbose_name = "Job"
db_table = "Job"
def __unicode__(self):
return self.title
我需要在模型中调整什么吗,请指导我!
【问题讨论】:
【参考方案1】:试试这个
from django.db.models import Count
# import your model (Job)
Job.objects.values('userId').annotate(c=Count('userId')).values('userId__name','c')
最初的values('userId')
后跟annotate
将按userId
进行计数和分组。
输出将是这样的字典列表:
['userId__name':'John','c':20,]
用户John
有20 个相关的Job
对象。
在不相关的说明中,只要您的模型中有外键。通常最好写user
而不是userId
。
编写查询和访问关系时更有意义(user__name
而不是userId__name
)。
更新:
如果您需要其他属性,请将它们作为参数添加到第二个 values
调用中,如下所示:
Job.objects.values('userId').annotate(c=Count('userId'))\
.values('userId__name','userId__email_id','c')
【讨论】:
感谢您提供出色的解决方案,您能帮助我如何从用户表中获取所有列而不是仅名称列 我已经更新了我的帖子来回答你的其他问题。 据我所知,您必须明确指定所需的所有属性。 答案非常有帮助,只是扩展问题是否有可能做一个 coulmn alise userId__name 看起来很奇怪我想做 name 因为我我在 api 中公开它。所以django可以让我们做类似userId__name as name的事情 有一种别名的方法,但不幸的是它没有通过这里的 cmets (***.com/a/10599077/1268926) 中描述的关系。您可以编写自己的函数来重命名所有键。api_return = ['name':k['userId__name'] for k in v]
其中 v 是我回答中的最后一个查询。【参考方案2】:
我认为最直接的解决方案是通过以下方式获取您的用户对象:
users = User.objects.filter(<filtering-expression-here>)
获得用户后,您可以通过以下方式考虑他的工作数量:
for user in users:
print "User '%s' has %s jobs" % (user.name, str(user.job_set.count()))
PS:此建议假设您将“用户”模型重命名为“用户”(不带 s)
编辑:我将 len(...) 更改为 .count()
【讨论】:
len
不适用于user.job_set
。你需要做user.job_set.count()
或len(user.job_set.all())
。即便如此,这种方法效率低下,因为您获取 User 对象的所有属性(使用过滤器),然后使用 user.job_set
获取所有相关作业(当您只需要计数时)。
没错,感谢您指出这一点。我同意你的表现评论。但是,以编程方式,这可能是最简单的事情。
在程序上是的,当您的数据库中有很多行和/或多列时,可伸缩性方面不太好。以上是关于如何通过 django 模型查询创建与组的左连接的主要内容,如果未能解决你的问题,请参考以下文章