将 Django ORM 用于计算字段
Using Django ORM for computed field
我有一个网络应用程序记分牌。每个用户post值10分,每条用户评论值1分。我想先按最高分排序。所以对于原始 SQL,它将是:
select username, email,
( select 10 * count(*) from posts_post where accounts_customuser.id = posts_post.author_id ) +
( select count(*) from posts_comment where accounts_customuser.id = posts_comment.author_id ) total
from accounts_customuser
order by total desc, username;
当然,Django 的想法是利用 ORM 并避免原始 SQL。我看到有聚合,所以它接近于这样的东西:
queryset = get_user_model().objects.annotate(post_count=Count('posts'),
comment_count=Count('comment')).order_by('-post_count', '-comment_count', 'username')
但是,这不太正确,因为如果我有一个用户有 1 个 post 和 1 个评论(11 分),然后有一个用户有 0 个 post 和 12 个评论(12 分),使用上述 QuerySet,它们不会被 ORM 正确排序。我尝试利用 F:
# Note: CustomUser is what get_user_model() returns
CustomUser.objects.annotate(post_count=Count('posts'), comment_count=Count('comment'),
total=Sum(F('post_count') * 10 + F('comment_count'))
).order_by('-post_count', '-comment_count', 'username')
但是,这会引发以下错误:
FieldError: Cannot compute Sum('<CombinedExpression: F(post_count) * Value(10) +
F(comment_count)>'): '<CombinedExpression: F(post_count) * Value(10) +
F(comment_count)>' is an aggregate
我不确定从这里到哪里去。有人能给我指出正确的方向吗?
得到了the answer from KenWhitesell on the Django forums:
显然使用 Sum 是一个错误,因为我的聚合是奇异值,所以解决方案是:
CustomUser.objects.annotate(
post_count=Count('posts'),
comment_count=Count('comment'),
total=F('post_count') * 10 + F('comment_count')
).order_by('-post_count', '-comment_count', 'username')
我有一个网络应用程序记分牌。每个用户post值10分,每条用户评论值1分。我想先按最高分排序。所以对于原始 SQL,它将是:
select username, email,
( select 10 * count(*) from posts_post where accounts_customuser.id = posts_post.author_id ) +
( select count(*) from posts_comment where accounts_customuser.id = posts_comment.author_id ) total
from accounts_customuser
order by total desc, username;
当然,Django 的想法是利用 ORM 并避免原始 SQL。我看到有聚合,所以它接近于这样的东西:
queryset = get_user_model().objects.annotate(post_count=Count('posts'),
comment_count=Count('comment')).order_by('-post_count', '-comment_count', 'username')
但是,这不太正确,因为如果我有一个用户有 1 个 post 和 1 个评论(11 分),然后有一个用户有 0 个 post 和 12 个评论(12 分),使用上述 QuerySet,它们不会被 ORM 正确排序。我尝试利用 F:
# Note: CustomUser is what get_user_model() returns
CustomUser.objects.annotate(post_count=Count('posts'), comment_count=Count('comment'),
total=Sum(F('post_count') * 10 + F('comment_count'))
).order_by('-post_count', '-comment_count', 'username')
但是,这会引发以下错误:
FieldError: Cannot compute Sum('<CombinedExpression: F(post_count) * Value(10) +
F(comment_count)>'): '<CombinedExpression: F(post_count) * Value(10) +
F(comment_count)>' is an aggregate
我不确定从这里到哪里去。有人能给我指出正确的方向吗?
得到了the answer from KenWhitesell on the Django forums:
显然使用 Sum 是一个错误,因为我的聚合是奇异值,所以解决方案是:
CustomUser.objects.annotate(
post_count=Count('posts'),
comment_count=Count('comment'),
total=F('post_count') * 10 + F('comment_count')
).order_by('-post_count', '-comment_count', 'username')