django内置了这个复杂的ORM,但是在花了很多时间之后,我仍然很难在SQL中进行非常简单的查询。甚至有一些简单的事情我无法通过django ORM找到办法(例如'从tablename'中选择distinct column1)。
是否有任何文档显示“对于常见的SQL语句,以下是如何在django中执行此操作”?
(我之前尝试过谷歌,但要么它不在那里,要么我想不出正确的查询......)
答案 0 :(得分:8)
在SQL中有一些非常简单的东西,通过ORM很难或不可能。这称为“object-relational impedance mismatch”。本质上,ORM将数据库中的每一行视为一个单独的对象。因此,涉及将值与其行分开处理的操作变得相当具有挑战性。 Django(1.1+)的最新版本使用aggregation support稍微改善了这种情况,但是对于很多东西,只有SQL可以工作。
为此,django提供了几种让你简单地下载到原始sql的方法。其中一些将模型对象作为结果返回,而另一些则将您一直带到DBAPI2连接器。最低级别看起来像这样:
from django.db import connection
cursor = connection.cursor()
cursor.execute("SELECT DISTINCT column1 FROM tablename")
row = cursor.fetchone()
如果要从SQL查询返回查询集,请使用模型管理器上的raw():
qs = ModelName.objects.raw("""SELECT first_name
FROM myapp_modelname
WHERE last_name = 'van Rossum'")
for person in qs:
print person.first_name # Result already available
print person.last_name # Has to hit the DB again
注意: raw()仅在Django的开发版本中可用,它应该从1.2版本合并到trunk。
Performing raw SQL queries下的文档中提供了完整信息。
答案 1 :(得分:6)
这样想。
“对于常见的SQL hack-arounds,我本来应该做的面向对象的事情是什么?”
问题不在于ORM是复杂的。这就是你的大脑在SQL模型中被扭曲,使得很难清楚地看到这些物体。
一般规则:
如果您认为这是一个简单的SELECT FROM WHERE,请停止。询问您需要在结果集中查看哪些对象。然后找到这些对象并使用对象管理器。
如果您认为这是一个简单的JOIN,请停止。询问你想要什么主要对象。请记住,对象不使用外键。加入并不意味着什么。对象似乎打破1NF并包含其中的整个相关对象集。然后找到“主要”对象并使用对象管理器。使用相关对象查询来查找相关对象。
如果您认为这是一个外部加入,请停止。询问您希望在结果集中看到哪两件事。外连接是将UNIONED与不会加入的东西连接起来的东西。首先是什么东西。然后找到“主要”对象并使用对象管理器。有些会有一组相关的对象。有些人不会。
如果您认为它是子查询的WHERE EXISTS或WHERE IN,则您的模型可能不完整。有时,它需要花哨的加入。但如果您正在进行此类检查,通常意味着您需要在模型中使用属性。
如果您认为自己需要SELECT DISTINCT,那么您完全错过了这条船。那只是一个Python集。您只需将列值放入Python集中即可。这些是不同的价值观。
如果您认为需要GROUP BY,则忽略Python collections.defaultdict
。使用Python到GROUP BY通常比使用SQL更快。
除数据仓库外。你不应该在Django做什么。您必须使用SQLAlchemy进行数据仓库。
答案 2 :(得分:4)
执行Django查询的一个很好的起点是Django文档本身。
http://docs.djangoproject.com/en/dev/topics/db/queries/
以下是一些例子:
select * from table
=
ModelName.objects.all()
过滤
select * from table where column = 'foo'
=
ModelName.objects.filter(column='foo')
特别是关于distinct的使用,请使用Django查询集的distinct()方法。
这是文档中的相关链接。 http://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct
更新: ORM允许您使用面向对象的数据交互来帮助您。您不会编写将查询的结果集转换为一组对象的代码。它自动完成。这是你必须做出的思想过程的根本改变。
你开始考虑'我有这个对象,我需要获得所有其他类似的对象'然后你可以向ORM询问这些对象。 ORM,我需要具有颜色“蓝色”
属性的Class Product的所有对象Django的具体ORM语言是:
products = Product.objects.filter(color='blue')
这样做而不是:
这是使用ORM的价值。简化代码并缩短开发时间。
答案 3 :(得分:2)
对于您的具体操作方法,您可以这样做:
MyModel.objects.values_list('column1', flat=True).distinct()
但其他海报说你不应该考虑'如何在ORM中编写这个SQL'是正确的。当你学习Python,来自Java或C ++或其他任何东西时,你很快就学会了摆脱“如何用Python编写这个Java代码”的思维方式,而只是集中精力用Python解决问题。使用ORM也是如此。