gpt4 book ai didi

django - 尝试使用子查询计算时差时出错

转载 作者:行者123 更新时间:2023-12-01 13:18:56 24 4
gpt4 key购买 nike

我跟踪人们在特定页面上花费的时间(我就这个问题提出了几个问题 here)。我注册页面加载的时间('Enter' 事件)。在一个单独的模型中,我注册了所有的“退出”:提交表单时,卸载页面时等。这个“退出事件”模型通过外键连接到 EnterEvent 模型,因为一个 Enter 事件可以并且通常确实有几个相应的退出事件。

EXITTYPES = [(0, 'form submitted'), (1, 'page unloaded'), (2, 'client disconnected')]


class EnterEvent(models.Model):
page_name = models.CharField(max_length=1000)
user = models.ForeignKey(to=User, related_name='enters')
timestamp = models.DateTimeField()
closed = models.BooleanField(default=False)


class ExitEvent(models.Model):
enter_event = models.ForeignKey(to=EnterEvent, related_name='exits')
timestamp = models.DateTimeField()
exit_type = models.IntegerField(choices=EXITTYPES)

要计算用户在页面上花费的时间,我使用以下正确工作的代码:
def get_time_per_page(user, page_name):
earliest = ExitEvent.objects.filter(enter_event=OuterRef('pk')).order_by('timestamp')
delta = timedelta(days=1)

a = EnterEvent.objects.filter(closed=True,
user=user,
page_name=page_name).annotate(
earliest_exit=Subquery(earliest.values('timestamp')[:1]),
).values()
sum_diff = sum([i['earliest_exit'] - i['timestamp'] for i in a], timedelta())

return sum_diff

但是,当我尝试在以下注释查询中使用子查询的结果时,它失败了:
b = EnterEvent.objects.filter(closed=True,
participant=player.participant,
page_name=page_name).annotate(
earliest_exit=Subquery(earliest.values('timestamp')[:1]),
).annotate(timespent=ExpressionWrapper(F('earliest_exit') - F('timestamp'), output_field=DurationField()))

错误日志:
Exception Type: TypeError
Exception Value: can only concatenate tuple (not "list") to tuple
Exception Location: /Users/chapkovski/otree2/lib/python3.6/site-packages/django/db/backends/sqlite3/operations.py in subtract_temporals, line 280

我究竟做错了什么?

更新:::

当 Django 尝试减去两个日期时会导致错误,其中一个是由 Subquery 生成的。
这特别是由于来自 'normal' 字段的参数是一个元组,而 Subquery 返回一个列表,所以当 Django(在 subtract_temporals 函数中)尝试对这两个求和时,它会带来一个错误:
 internal_type   'DateTimeField'
lhs_params ()
rhs_params []

最佳答案

这个月我两次遇到这个问题,最后我找到了一个对我有用的黑客。我想在 QuerySet 中进行计算,这样我就可以从数据库排序中受益,而不必在用户想要按持续时间字段排序时编写自定义排序。

所以我找到的解决方案是通过子查询对两列进行注释,因此最终结果将是两列在内部都是一个列表,因此 Django 将成功连接/正确计算持续时间,而不会产生 ValueError 异常。

这是使用您的代码的示例:

from django.db.models import Subquery, OuterRef, F, ExpressionWrapper, DurationField

earliest = ExitEvent.objects.filter(enter_event=OuterRef('pk')).order_by('timestamp')
enter_timestamp = EnterEvent.objects.filter(pk=OuterRef('pk')).annotate(enter_timestamp=F('timestamp'))

EnterEvent.objects.filter(closed=True, participant=player.participant, page_name=page_name) \
.annotate(earliest_exit=Subquery(earliest.values('timestamp')[:1])) \
.annotate(enter_timestamp=Subquery(enter_timestamp.values('enter_timestamp')[:1])) \
.annotate(timespent=ExpressionWrapper(F('earliest_exit') - F('enter_timestamp'), output_field=DurationField()))

关于django - 尝试使用子查询计算时差时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51684256/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com