0

我有一组 django 模型,如下所示:

class Foo(models.Model):
    ...

class FooVersion(models.Model):
    name = models.CharField(max_length=100)
    parent = models.ForeignKey(Foo)
    version = models.FloatField()
    ...

我正在尝试创建一个显示所有 Foos 的 Django ListView,按其最高版本名称的字母顺序排列。例如,如果我有一个如下所示的数据集:

version_id | id |           version_name            | version 
-----------+----+-----------------------------------+---------
         1 | 1  | Test 1                            |      1.0
         2 | 1  | Test 2                            |      2.0
         3 | 1  | Test 2                            |      3.0
         4 | 2  | Test 1                            |      1.0
         5 | 1  | Test 3                            |      2.5
         6 | 3  | Test 3                            |      1.0

我希望查询返回:

version_id | id |           version_name            | version 
-----------+----+-----------------------------------+---------
         4 | 2  | Test 1                            |      1.0
         3 | 1  | Test 2                            |      3.0
         6 | 3  | Test 3                            |      1.0

我将用来生成它的原始 sql 是:

SELECT version_class.id as version_id, someapp_foo.id, version_class.name as version_name, version_class.version
FROM someapp_foo
INNER JOIN(
    SELECT someapp_fooversion.name, someapp_fooversion.version, someapp_fooversion.parent_id, someapp_fooversion.id
    FROM someapp_fooversion
    INNER JOIN(
        SELECT parent_id, max(version) AS version
    FROM courses_courseversion GROUP BY parent_id)
AS current_version ON current_version.parent_id = someapp_fooversion.parent_id
AND current_version.version = someapp_fooversion.version)
AS version_class ON version_class.parent_id = someapp_foo.id
ORDER BY version_name;

但是我在使用原始查询时遇到了问题,因为 RawQuerySet 对象没有“count”方法,ListView 调用该方法进行分页。我已经研究了 Django 查询集的“额外”功能,但是我在制定一个可以使用它的查询时遇到了麻烦。

我将如何制定一个“额外”的查询来获得我正在寻找的东西?或者有没有办法将 RawQuerySet 转换为常规 QuerySet?任何其他可能的解决方案来获得我正在寻找的结果?

4

3 回答 3

0

可能有更好的方法来做到这一点,但现在我正在尝试一个似乎有效的自定义解决方案:

from django.db import models
from django.db.models.query import RawQuerySet

class CountableRawQuerySet(RawQuerySet):
   def count(self):
       return sum([1 for obj in self])

class FooManager(models.Manager):
    def raw(self, raw_query, params=None, *args, **kwargs):
        return CountableRawQuerySet(raw_query=raw_query, model=self.model, params=params, using=self._db, *args, **kwargs)

class Foo(models.Model):
    objects = FooManager()

然后我的查询集是:

Foo.objects.raw(sql)

关于如何改进的建议?

于 2012-08-14T19:46:49.173 回答
0

首先-您的解决方案是错误的,并且对大量数据非常无效。我相信你只需要这样的东西:

from django.db.models import Max
Foo.objects.annotate(max_version=Max(fooversion__version))

您现在可以max_version将每个结果中的属性称为普通属性。有关详细信息,请参阅https://docs.djangoproject.com/en/dev/topics/db/aggregation/

于 2012-08-14T22:37:47.553 回答
0

要补充的另一点是,只要您不使用分页,RawQuerySet 就可以与 ListView 一起正常工作,即您可以paginate_by = NN从 ListView 子类中省略该属性。

于 2018-02-09T09:22:34.713 回答