扩大Django的ORM[译]

注:译文,原文地点http://blog.safaribooksonline.com/2013/11/06/extending-the-django-orm/

Django的对象关联映照(ORM)在代码和数据库之间搭起了一架桥梁。这篇文章中我盘算扼要的说下什么是ORM以及该怎样去运用它。最主要的是怎样运用特地的SQL定制和扩大ORM。
末了,我会说几点为何在不挑选规范ORM时须要迥殊的警惕。如今最先吧。

ORM的什么吸收我?

起首,也是最主要的,ORM会将营业逻辑封装进运用中,而不是运用数据库。将运用的营业逻辑放进ORM让我们的代码更轻易明白和保护。他让我们不必再一直去猜运用究竟是怎样事情的。

ORM帮我们在数据库返回和插进去数据时举行考证。在对数据的完整性和安全性异常体贴的运用中,这一步是起决定性作用的。虽然数据库中的范例搜检也异常的棒,然则Django的ORM能协助
我们在数据没有抵达数据库的时刻考证营业划定规矩。另外,也能保证数据库返回的数据是我们所希冀的。

MyModelClass.objects.all() 是ORM的一个异常简朴的运用ORM的例子。这行代码返回数据表中的一切内容,与select * from MyModelTable效果一样。另有许多其他的用法,
这不是这篇文章的关注的。在你最先运用定制的SQL语句之前你将会异常想晓得ORM是怎样事情的。

为何我须要定制ORM?

在实践中,我见过几个例子。起首是当没有显著的查询要领的时刻你会这么想。但是这关于定制ORM不是一个很好的假定。当你须要运用SQL的时刻,试着运用对象和对象关联来思索,而不是运用数据表。
这可能会取得一个很好的查询要领。举个例子,许多的SQL用户或许想写下面的语句:

SELECT
"user_user"."id", "user_user"."password",  
"user_user"."last_login", "user_user"."name",
"user_user"."date", "user_user"."level"  
FROM  
"user_user"
INSERT JOIN  
"address_address"
ON ("user_user"."id" = "address_address"."user_id")
WHERE ("user_user"."name" IN (hello, world) AND "address_address"."street" = main)  

假如这些数据模型建立的准确的话,响应的Python代码异常简朴:

User.objects.filter(name__in=['hello', 'world'], address_street='main')  

关于偏向运用SQL的用户,我发起经常往回退一步。关于Python/Django的重度用户,我发起记着用SQL的头脑来想想将会建立的是什么。运用SQL来扩大和定制的缘由更准确的说应当是:
有一个异常特别的逻辑或许能取得更好的ORM不能供应的机能。

我怎样定制查询?

第一个定制查询的挑选是运用extra要领,文档很细致。Django文档中供应了很棒的例子
我将会运用raw来完成一个很好的用例,raw文档一样很棒。但是这些例子都不怎样主要。
我想让你经由历程ORM来运用用先进数据库特征的上风。

举个例子,如今你的运用须要展示一个聚合了许多值的大数据,须要建立大批的SQL语句。第一步,你将建立一个存储历程来封装这个查询,然后建立一个SQL function来让轻易挪用这个查询(你一样须要
建立一个数据表,但那都是规范的SQL)。为了机能,你或许你将这个逻辑移到了数据库中去处置惩罚。所以,这时刻你的运用只能在数据库完成数据聚合的时刻才处置惩罚营业逻辑。

我们一样假定你有一个名为aggregate_profile_metrics的SQL要领来协助你的运用进步机能。运用规范的ORM的话你就没这么荣幸了。SQL要领只需在运用views和tables的时刻才运用。如今看看raw
查询的威力。起首定义一个model。

class ProfileMetric(models.Model):
    avg_posts_per_day = models.IntegerField()
    avg_comments_per_day = models.IntegerField()
    avg_respondees_per_day = models.IntegerField()

    class Meta():
        managed = False
        db_table = 'fake_table_name'  # This is the trickier part  

注重这个model是完整与数据相干的,我们能够在我们一切差别的数据表中举行聚合挪用。当数据库足够大,你具有数十个表和数百万用户的时刻,这个表就有肯定范围了。因为这些数据极可能随时更新,这时刻SQL要领
的效力上风就显示出来了。如今进入最风趣的部份,运用下面的要领你将很轻易到达挪用SQL要领的目标。

query = "select avg_posts_per_day, avg_comments_per_day, avg_respondees_per_day 
         from table(aggregate_profile_metrics(%s))"  

profile_metrics = ProfileMetric.objects.raw(query, [283844238])

运用上面的查询你能够挪用SQL要领,然则这太痛苦了。注重,这个SQL要领挪用了一个参数user_id来猎取数据,然则我们没有将参数直接通报进去。假如你的SQL要领不须要挪用参数,你应当运用数据库的view
运用这个要领,你如今能够运用profile_metics,除了一些微小的区分外,就像运用一个平常的queryset一样(检察RawQUeryset和平常Queryset的区分)。

除了这点,Django还许可用户不经由历程model举行数据库操纵。我尽力阻挡这么做。记着不运用model直接举行数据库操纵是没多少来由的。那些运用了这个的例子都是异常极度的状况。只需运用了不基于model的raw查询,
ORM的作用就消逝了。从这点来讲,就没有运用Django的必要了。

当运用.raw的时刻,须要记着一下几点。

  1. 确认这些查询不能运用Django的ORM完成。

  2. 确认须要去建立定制的SQL(比方:为了取得SQL function的机能或许是在遗留运用中举行的操纵)。

  3. 经由历程QuerySet中的.raw来建立你定制的SQL挪用。

  4. 不要直接运用connectioncurser.execute

如今,你晓得Django的ORM是异常壮大的。当你想运用SQL语句和敕令的时刻记着这一点。记着下面关于什么时候运用raw SQL的发起。

  1. 不要运用raw SQL(当你能用其他方法处理的时刻)。

  2. 运用ORM中的对象关联。

  3. 试着在运用raw前运用extra,

  4. 将raw作为末了一个挑选。

    原文作者:木头lbj
    原文地址: https://segmentfault.com/a/1190000000334852
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞