我想减去创建用户的结果对象和用户注册的时间。这些是我的型号:
class User(AbstractUser):
id = models.AutoField(primary_key=True)
created_at = models.DateTimeField(auto_now_add=True)
username = models.CharField(unique=True, max_length=13)
first_name = models.CharField(max_length=32, null=True, default=None)
last_name = models.CharField(max_length=64, null=True, default=None)
class Results(models.Model):
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
created = models.DateField(auto_now_add=True, blank=True, null=True)
score = models.FloatField()
在我的观点中,我想要这样的东西:(所有Results.created日期的总和-所有User.created_at日期的总和(/len(所有用户(。我怎样才能做到这一点?
我使用聚合编写了这行代码进行测试:
Results.objects.filter(user__is_staff=False, user__role='applicant').aggregate(Avg(F('created')))
但它给了我一个错误:
You cannot use Sum, Avg, StdDev, and Variance aggregations on date/time fields in sqlite3 since date/time is saved as text.
我假设您正在计算用户帐户创建日期和每个测验完成日期之间的平均差值。假设我们有三个结果:
- 用户A在创建帐户3天后完成测试
- 用户A在创建帐户4天后完成第二次测试
- 用户B在创建帐户5天后完成测试
计算将是3、4和5的平均值。
您可以使用Django的查询表达式来实现这一点。
- 为了获得更好的准确性,请将
Results
中的created
字段更改为DateTimeField
,而不是DateField
。否则,您的计算将无法计算部分天数 - 使用
F
函数引用所需字段:F('created')
指Result
的创建日期,F('user__created_at')
指Result
对应的User
的帐户创建日期 - 使用
Func
创建一个JulianDay
类,该类表示SQLite的JulianDay函数。此函数用于查找两个日期之间的天数 - 使用
FloatField()
作为输出字段的数据类型,计算Avg
聚合。(注意:一旦将Results
中的created
字段更改为DateTimeField
,就可以删除output_field=FloatField()
部分。(
# Import your models
from question70860461.models import User, Quiz, Results
# Import Django query expressions
from django.db.models import F, Func, FloatField, Avg
# Set up some example objects
u = User(username='jeffb', first_name='Jeff', last_name='Booth')
u.save()
q = Quiz()
q.save()
r = Results(quiz=q, user=u, score=100)
r.save()
r2 = Results(quiz=q, user=u, score=200)
r2.save()
# The usual trick to find the days between two dates on SQLite
# is to use the JulianDay function. Create a Django Func wrapper
# for this function:
class JulianDay(Func):
function='JulianDay'
# Run a query that finds the average
# time between User creation and Results creation.
x = Results.objects.aggregate(
result=Avg(JulianDay(F('created')) - JulianDay(F('user__created_at')),
output_field=FloatField()))