Django ORM Group By Field By另一个字段



我有SessionLog模型

class SessionLog(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
ip_address = models.CharField(max_length=20, null=True)

我想获得的ip地址的列表只为重复的用户。因此,如果不同的用户使用相同的IP地址登录,我想获得这些IP地址的列表。

另外,我想获得登录相同ip的用户列表。

所以预期结果是

[
{
"ip_address": "170.221.23.56",
"user_id": [21, 23, 45]
},
{
"ip_address": "170.221.23.58",
"user_id": [25, 23, 45]
},
]

如何用django实现ORM?

如果你正在使用PostgreSQL,你可以这样做:

from django.db import models
from django.contrib.postgres.fields import ArrayField

class Array(models.Subquery):
template = 'ARRAY(%(subquery)s)'
output_field = ArrayField(base_field=models.TextField())
user_ids = SessionLog.objects.filter(
ip_address=models.OuterRef("ip_address")
).values_list("user_id", flat=True)
sessions = SessionLog.objects.distict("ip_address").order_by("ip_address").annotate(
user_ids=Array(user_ids)
)
for session in sessions:
print(session.ip_address, session.user_ids)

如果您使用的是另一个数据库,您可以使用prefetch_related()进行查询(注意,这将导致两个查询而不是一个,但这应该不是一个真正的缺点)。

from django.db.models import Count
users_in_log = User.objects.prefetch_related("session_log_set")
users_in_log = users_in_log.annotate(session_count=Count("session_log_set"))
users_in_log = users_in_log.filter(session_count__gt=0).distinct()
for user in users_in_log:
print(user.pk, [s.ip_address for s in user.session_log_set.all()]

您可以首先将查询集转换为列表:

ip_list = list(SessionLog.objects.values_list('ip_address'))
user_list = list(SessionLog.objects.values_list('user'))

然后创建另一个列表来标识唯一的IP地址:

unique_addresses = list(set(ip_list))

最后使用enumerate获取IP地址的索引,然后使用这些索引获取用户对应的值,如下所示:

Dict = {} 
users = [] 
for n in unique_addresses: 
indices = [i for i, x in enumerate(ip_list) if x == n] 
for p in indices: 
users.append(user_list[p]) 
Dict[n] = status 
status = [] 
print(Dict)

输出格式有点乱,但是您可以使用Dict['ip_address']

访问特定ip地址的用户。另一种方法是循环遍历数据库中的每个条目并动态执行排序,但这将涉及多个可能影响性能的请求

相关内容

  • 没有找到相关文章

最新更新