django - SQL用户的ORM指南?

时间:2010-02-04 19:47:33

标签: sql django orm

django内置了这个复杂的ORM,但是在花了很多时间之后,我仍然很难在SQL中进行非常简单的查询。甚至有一些简单的事情我无法通过django ORM找到办法(例如'从tablename'中选择distinct column1)。

是否有任何文档显示“对于常见的SQL语句,以下是如何在django中执行此操作”?

(我之前尝试过谷歌,但要么它不在那里,要么我想不出正确的查询......)

4 个答案:

答案 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')

这样做而不是:

  • 编写sql查询,
  • 正确转义所有参数,
  • 连接数据库,
  • 查询数据库并处理连接/查询错误,
  • 获取结果集,
  • 遍历结果集,将返回的值转换为可以调用方法的正确对象。

这是使用ORM的价值。简化代码并缩短开发时间。

答案 3 :(得分:2)

对于您的具体操作方法,您可以这样做:

MyModel.objects.values_list('column1', flat=True).distinct()

但其他海报说你不应该考虑'如何在ORM中编写这个SQL'是正确的。当你学习Python,来自Java或C ++或其他任何东西时,你很快就学会了摆脱“如何用Python编写这个Java代码”的思维方式,而只是集中精力用Python解决问题。使用ORM也是如此。