将原始 SQL 转换为 Django QuerySet
Convert raw SQL to Django QuerySet
有人可以展示如何将以下 SQL 查询转换为 Django QuerySet 调用吗?我是 Django 的新手,我可以使用原始查询,但了解如何将此查询编写为本机 Django 调用对我来说很有趣。
用户和个人资料有 2 个模型 1:1
如果相同的 phone 号码出现在 2 个或更多个人资料中,我需要从用户和个人资料中获取 phone 的电子邮件。
SELECT
GROUP_CONCAT(u.email) as emails, p.phone as phone_number
FROM
profile AS p JOIN auth_user AS u on u.id = p.user_id
GROUP BY
phone
HAVING
COUNT(phone) > 1
这是我尝试做的事情:
from myapp.models import Profile
from django.db.models import Count
Profile.objects
.exclude(phone='')
.annotate(phone_count=Count('phone'))
.values('phone')
..结果是:
[
{
'phone': '***'
},
{
'phone': '***'
}
]
如果在查询中添加.filter(phone_count__gt=1)
则返回空结果(不明白为什么)。
期望的输出是:
[
{
'phone': '***',
'emails': 'user1@mail.com'
},
{
'phone': '***',
'emails': 'user2@mail.com,user3@mail.com'
}
]
UPD
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone = models.CharField(max_length=100, blank=True, null=True)
from myapp.models import Profile
from django.db.models import Count
qs = Profile.objects.exclude(
phone=''
).exclude(
phone__isnull=True
).values('phone').annotate(
phone_count=Count('user_id')
).filter(
phone_count__gt=1
).values_list('phone', flat=True)
# the above will get you a list of phone numbers that appear more than once
# now get the user_ids, too, and add in the emails
qs = Profile.objects.filter(phone__in=qs).values_list('user__email', 'phone')
# now convert to a dict
from collections import defaultdict
data = defaultdict(list)
for email, phone in qs:
data[phone].append(email)
# now convert to desired format
result = [{
'phone': phone,
'emails': ','.join(emails),
} for phone, emails in data.itervalues()]
# Of course, you could always just use raw and do a raw
# SQL query as described here: https://docs.djangoproject.com/en/1.9/topics/db/sql/#executing-custom-sql-directly
有人可以展示如何将以下 SQL 查询转换为 Django QuerySet 调用吗?我是 Django 的新手,我可以使用原始查询,但了解如何将此查询编写为本机 Django 调用对我来说很有趣。
用户和个人资料有 2 个模型 1:1 如果相同的 phone 号码出现在 2 个或更多个人资料中,我需要从用户和个人资料中获取 phone 的电子邮件。
SELECT
GROUP_CONCAT(u.email) as emails, p.phone as phone_number
FROM
profile AS p JOIN auth_user AS u on u.id = p.user_id
GROUP BY
phone
HAVING
COUNT(phone) > 1
这是我尝试做的事情:
from myapp.models import Profile
from django.db.models import Count
Profile.objects
.exclude(phone='')
.annotate(phone_count=Count('phone'))
.values('phone')
..结果是:
[
{
'phone': '***'
},
{
'phone': '***'
}
]
如果在查询中添加.filter(phone_count__gt=1)
则返回空结果(不明白为什么)。
期望的输出是:
[
{
'phone': '***',
'emails': 'user1@mail.com'
},
{
'phone': '***',
'emails': 'user2@mail.com,user3@mail.com'
}
]
UPD
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone = models.CharField(max_length=100, blank=True, null=True)
from myapp.models import Profile
from django.db.models import Count
qs = Profile.objects.exclude(
phone=''
).exclude(
phone__isnull=True
).values('phone').annotate(
phone_count=Count('user_id')
).filter(
phone_count__gt=1
).values_list('phone', flat=True)
# the above will get you a list of phone numbers that appear more than once
# now get the user_ids, too, and add in the emails
qs = Profile.objects.filter(phone__in=qs).values_list('user__email', 'phone')
# now convert to a dict
from collections import defaultdict
data = defaultdict(list)
for email, phone in qs:
data[phone].append(email)
# now convert to desired format
result = [{
'phone': phone,
'emails': ','.join(emails),
} for phone, emails in data.itervalues()]
# Of course, you could always just use raw and do a raw
# SQL query as described here: https://docs.djangoproject.com/en/1.9/topics/db/sql/#executing-custom-sql-directly