在Django中用SQLite儒略日做原生SQL聚合时遇类型错误
问题解决:计算last_played与当前时间天数差的平均值
你遇到的错误是因为Django的aggregate()方法要求传入的是Django内置的聚合表达式(如Avg、Sum),而RawSQL本身不属于聚合表达式类型,因此无法被识别。以下是两种可行的解决方案:
方案一:直接使用原生SQL查询(最直接)
绕过ORM的聚合限制,直接执行原生SQL语句:
from django.db import connection def get_avg_days_last_played(): with connection.cursor() as cursor: # 替换`song_song`为你的实际表名(Django默认格式为「应用名_模型名」) cursor.execute(""" SELECT AVG(julianday('now') - julianday(last_played)) FROM song_song; """) result = cursor.fetchone() # 无记录时返回None return result[0] if result else None average_days_last_played = get_avg_days_last_played()
方案二:自定义聚合函数(符合Django ORM规范)
通过自定义聚合类,让Django识别你的SQL逻辑为合法的聚合表达式:
from django.db.models import Aggregate, FloatField class AvgDaysSinceLastPlayed(Aggregate): function = 'AVG' # 模板中注入SQL逻辑,%(expressions)s会自动替换为传入的字段名 template = "%(function)s(julianday('now') - julianday(%(expressions)s))" output_field = FloatField() # 使用自定义聚合计算平均值 average_days_last_played = Song.objects.aggregate( avg_days_last_played=AvgDaysSinceLastPlayed('last_played') )['avg_days_last_played']
注意事项
确保代码中的字段名与你模型中定义的一致:问题描述中提到的是last_played,但你原代码里用了played_at,需统一避免字段名错误。
内容的提问来源于stack exchange,提问作者Tjorriemorrie
相关产品推荐
相关产品推荐

