我目前正在尝试计算用户活动,但只会在首次注册后两天计算。由于我将对数据进行后处理,我想让它返回一个Django QuerySet。
唯一相关的字段如下:
User
user_id, install_time
Activity
user_id, date, [list of activities]
虽然我已经将解决方案混合在一起,但效率非常低(O(n²)),因为我必须在连续的user_id
循环中单独匹配for
。
目前,ForeignKey
字段不适合我的模型。我找到了this;但是,我找不到只返回user_id
匹配的date > install_time + datetime.timedelta(2)
和class User(models.Model):
user_id = models.CharField(max_length=36)
install_time = models.DateTimeField()
class Activity(models.Model):
user_id = models.CharField(max_length=36)
date = models.DateTimeField()
# Misc activity-related fields
的查询集的方法。
有什么想法吗?
编辑:这是我的模特:
{{1}}
答案 0 :(得分:2)
如果没有看到你的模型,就不可能给你任何明确的方向,但是Django的查询API支持遍历模式。
您可能会执行以下操作:
from django.db.models import F
Activity.objects.filter(date__gt=F('user__install_time')+timedelta(2))
更新(基于修改)
设置模型的方式效率低下,不允许您利用上述代码。特别是,您应该在User
上拥有Activity
的外键。
class Activity(models.Model):
user = models.ForeignKey(User)
date = models.DateTimeField()
...
在user_id
上使用User
可能也不是最佳选择。即使您没有直接指定它(或者我认为因为您没有直接指定它),Django会自动向您的模型添加id
字段,该字段是主键。你的桌子。所以你的模型实际上是 :
class User(models.Model):
id = models.AutoField()
user_id = models.CharField(max_length=36)
install_time = models.DateTimeField()
在您的模型上同时使用id
和user_id
令人困惑。如果user_id
与用户名相似,则将其重命名为username
。否则,你可能根本不需要它。
最后,奇怪的是你实际上首先定义了一个User
类。如果您打算使用Django的auth
包进行身份验证和用户管理,那么您将遇到巨大的问题(这意味着您永远不会真正定义您的永远拥有User
,以防万一)。如果您需要向内置User
添加额外字段,则可以使用配置文件模型执行此操作。请参阅:https://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
答案 1 :(得分:2)
由于您的模型没有使用显式连接,因此您不能像Chris Pratt建议的那样使用字段F
对象。
如果您无法修改架构,我可以看到另外两个仍然利用某些django ORM的选项,但是需要您编写SQL查询/片段。
我假设postgresql并且完全猜测django可能来自您所说的模型中的django没有正确命名。
QuerySet.extra
E.g:
activity_set = Activity.objects.extra(
tables=['myapp_user'],
where=[
"myapp_activity.user_id=myapp_user.user_id",
"myapp_activity.date - myapp_user.install_time > '2 days'"
])
使用extra
可能很尴尬,您可以通过str(activity_set.query)
检查它生成的sql。
或者,您可以使用Manager.raw
并完全手工制作查询。 E.g:
activity_set = Activity.objects.raw("""
SELECT
myapp_activity.* from myapp_activity, myapp_user
WHERE
myapp_activity.user_id=myapp_user.user_id
and myapp_activity.date - myapp_user.install_time > '2 days'
""")