我有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地址的用户。另一种方法是循环遍历数据库中的每个条目并动态执行排序,但这将涉及多个可能影响性能的请求