这是我在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的托管查询的输入,这支持点符号)。
答案 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)
我认为你对raw
在models.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")
应该做你想做的事。与原始的原始查询相比,它会再次获取作者的查询,但这可能是可以接受的,而不必处理裸机数据库查询。