如何在使用django.db时将原始SQL与ORM API混合?
ORM工具在我们需要简单的查询,比如select
(选择)或insert
(插入)时非常好用。
但是有时候,我们可能需要使用原始SQL查询,因为有些查询太复杂了,单靠ORM的接口无法提供高效和有效的解决方案。
那么,你会怎么处理从原始查询和ORM查询返回的对象之间的差异呢?
2 个回答
SQLAlchemy 让我们在写 查询 时可以处理很多复杂的事情,所以通常不需要直接写原始的 SQL 语句。如果确实需要用到原始 SQL,可以使用 connection.execute
。不过,还有一些辅助工具,比如 text
和 select
函数,可以让编程变得更简单。当你处理返回的对象时,你会得到一个元组的列表,这在 Python 中处理起来非常方便。
一般来说,如果你想把行(比如元组列表等)当作 ORM 返回的结果来处理,一种方法是写一个适配器类,模拟查询集的接口。这个适配器可以用返回的元组的“结构”来初始化,然后遍历这些元组,返回带有属性的对象,而不是简单的元组。我个人并没有真正需要这样做,但我能理解如果你有一个依赖于查询集传递的框架,这样做可能会很有用。
我个人的目标是设计我的模型,这样就不需要直接写原始的SQL查询,或者在复杂关系中使用ContentTypes
框架,所以我在这个话题上没有经验。
文档中讲到了如何使用API来执行原始SQL查询。你可以在你的模型上使用Manager.raw()
(比如MyModel.objects.raw()
),适用于那些可以将列映射回实际模型字段的查询,或者使用cursor
来直接查询数据库中的原始数据。
如果你打算使用Manager.raw()
,那么你将处理RawQuerySet
,而不是通常的QuerySet
。在处理结果对象时,这两者的表现是一样的,但QuerySet
功能更丰富。
我可以想象,在Django中执行原始SQL查询会比在没有ORM支持的框架中工作要更有成就感——Django可以管理你的数据库结构,并为你提供数据库连接,你只需要手动创建查询和设置查询参数。得到的结果可以作为列表或字典来访问,这两种方式都适合在模板中显示或进行进一步处理。