在Django中将文字值添加到QuerySet

Big*_*oke 2 python sql sqlite django django-models

我正在尝试根据在许多比赛中获得的积分为球队分配排名。得分更高的球队排名更高,如果得分相等,则比赛次数最少的球队排名更高。团队可以拥有同等的排名。

因为Django(也不是SQLite)支持DENSE_RANKwindow函数,所以我必须在Python中计算等级。尽管起初我是在返回的模型实例上执行此操作的all(),但我还是决定可以在QuerySet返回annotate().order_by()QuerySet对象上添加等级,同时保留要使用的对象,例如与get()

class TeamManager(models.manager):
    @staticmethod
    def add_ranking(qs):
        # First, populate rows and rankings lists
        # ...
        # Then, add it to the query set
        literal_selects = []
        for row_id, ranking in zip([row.id for row in rows], rankings):
            literal_selects.append('SELECT {} AS "thing_id", {} AS ranking'.format(row_id, ranking))
        extra_from = "(" + " UNION ALL ".join(literal_selects) + ")"

        return qs.extra(
            tables=[extra_from],
            select={'ranking': 'ranking'},
            where=['team.id = thing_id'])

    def ranked_list(self):
        qs = self.model.objects.annotate(
            num_games=Count('team__score_set'),
            total_points=Sum('team__score_set__points'),
            # Ideally, I would calculate ranking here
        ).order_by('-total_points')

        return TeamManager.add_ranking(qs)
Run Code Online (Sandbox Code Playgroud)

这是行不通的,因为Django的ORM 在其中的“表名”周围添加了双引号extra(table)

还有其他方法可以将文字值添加到预先存在的QuerySet,还是我必须用的调用替换要注释的调用raw(),然后从那里开始工作?太可惜了,因为我花了相当多的时间来理解如何将原始的原始SQL查询(使用GROUP BYs和所有东西)转换成更像Django的工作方式。我很乐意使用Django,而不是跳到我自己的旧SQL调子上。

Gag*_*aro 6

您可以使用Value添加文字值:

qs = self.model.objects.annotate(
    num_games=Count('team__score_set'),
    total_points=Sum('team__score_set__points'),
    ranking=Value(42, output_field=IntegerField())
).order_by('-total_points')
Run Code Online (Sandbox Code Playgroud)