Django原始查询 - 使用点表示法遍历相关模型的字段

时间:2014-08-24 08:09:04

标签: python django django-queryset

这是我在Django中的raw查询

q = Book.objects.raw('''
      SELECT * FROM 
        ( SELECT "book"."name", "author"."name", 
                 RANK() OVER (PARTITION BY "author"."id") AS "rank"
          FROM "book"
          INNER JOIN "book" ON ("book"."author_id" = "author"."id")
        ) AS "book_table"
      WHERE "rank" < %s ''', 10)

在上面的查询集中,name字段不明确。我将此对象传递给另一个需要使用点符号的库,即q[0].name应该引用该书的名称,q[0].author.name应该引用作者的名字。是否可以在原始查询中使用点表示法(最后的方法是使用"author"."name" AS "author_name",但是这会引入冗余代码,因为这些函数也接受来自Django的托管查询的输入,这支持点符号)。

2 个答案:

答案 0 :(得分:-1)

尽可能使用Django自己的查询语法可能会更好,并且只能手动添加rank字段。您可以使用extra而不是raw执行此操作,并使用select_related来遍历关系。像这样:

Book.objects.select_related('author').extra(
    select={'rank': 'RANK() OVER (PARTITION BY "author"."id")'},
    where=['"rank" < 10']
)

答案 1 :(得分:-1)

我认为你对rawmodels.manager的上下文中的含义感到困惑。

您可以使用FooModel.objects.raw为FooModel创建一个查询集(实际上是一个RawQuerySet);传递给raw的查询结果将转换为FooModels;因此,您应该只返回与FooModel相关的字段。有关示例,请参阅文档中的here。不确定哪些附加字段(比如你的例子中的author.name)会做什么,但我的猜测是它会混淆Django而不是你打算做它。

如果要运行完全任意的命令来返回任意数据,则需要直接与数据库here进行对话。

在你的情况下,做

q = Book.objects.raw('''
      SELECT "book"."id" FROM 
    ( SELECT "book"."id" 
             RANK() OVER (PARTITION BY "author"."id") AS "rank"
      FROM "book"
      INNER JOIN "book" ON ("book"."author_id" = "author"."id")
    ) AS "book_table"
  WHERE "rank" < %s ''', 10)
).prefetch_related("author")

应该做你想做的事。与原始的原始查询相比,它会再次获取作者的查询,但这可能是可以接受的,而不必处理裸机数据库查询。