Django的数据模型层实现特点

本文探讨了随着项目规模扩大,简单的ActiveRecord模式难以满足需求的问题,并介绍了作者在climbPHP框架中采用的一种通过事件驱动模块间交互的设计思路。此外,文章还详细分析了Django ORM在查询优化方面的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我在数据层的抽象上走了一段比较长的弯路。简单总结一下:

刚开始做简单的项目时,用简单的ActiveRecord就已经很合适了,比如CodeIgniter自带的。但是项目变大之后,特别是业务实体之间的关联变多之后马上就出现了问题,为了降低各个实体间的耦合,你需要将各种操作再抽象出一层。举个例子:你做了一个简单的用户系统,对用户的增删改查只需要对“用户类”调用相应的操作就行了。后来你增加了一个文件类,每个用户可以拥有多个文件,删除用户时需要同时删除相应的文件。为了能使删除的用户的这个操作复用,同时防止其他操作删除用户时没有删除相应文件夹,于是你不得不再对用户的删除做一层封装。我曾经试图让各种实体在构建的时候就说明与其他实体的关系,这样写业务逻辑的时候就能尽量少的受打扰。后来发现这也是错误的,因为把关系写到数据层以后,遇到特殊的逻辑就很难操作了。还是刚才那个例子:如果有一天我增加了一个分享功能,同时规定删除用户时不删除他已经分享的文件,这时该怎么办?当然有些其他绕的方法可以实现,比如分享文件的时候就复制文件到另一个特殊的用户账户下,用户读取的分享文件其实都是这个特殊用户账户的。但是系统大了之后,这种特殊方法就会多得烦人。后来在我写climbPHP时,才算是找到了一个较为合理的方法。就是系统应该以具体的业务逻辑来分模块,数据实体是从属于业务逻辑模块的。模块间的联系是通过抛出和监听事件实现的。数据实体之间不再有直接的关联。还是以刚才的背景来举例子:系统分为用户、文件、分享三个模块,用户模块接受正常的删除指令,成功后向外抛出事件。文件模块监听用户删除事件,同时删除相应的文件。分享模块也监听用户删除事件,监听到之后获取用户除了分享出去的文件以外可删除的文件,然后阻断原来的用户删除事件,改为抛出可删除文件的事件。这样的好处在于,每一个模块开发完成之后都可以完全封闭。当系统关闭共享模块时,原有系统不需要任何改动,仍然可用。不过这样做的前提在于需要有一个足够强大的事件派发中心。参见climbPHP

对ORM我没有用到过真正的项目中,一是因为有些业务逻辑太复杂,调研的ORM都不能满足性能上的需求。二是因为语法太难看,不想用。学Django的时候发现Django的数据模型层很成熟,具体特点记录如下:

1.对关联实体查询的优化。

这一部分应该是最影响数据库性能的。Django在查询有关联实体的实体时,默认时先查询主实体,然后根据关联项依次查询对关联实体。如果你查询的主实体是多个,那么会依次对每一个再去数据库查询相关联的实体。为了优化,Django提供了一个prefetch_related方法,能一次性查询所有相关联的实体,然后通过python组装。对于一对一的关联,Django还提供了selecte_related方法,这个方法使用的join来查询。

除了在查询方法上加速,Django还支持“关联对象”的延迟加载,也就是当访问关联的对象时才再次访问数据库。这一点我特别注意了一下,因为最近读了优快云范凯的关于ORM的总结,他说实际项目中数据库的瓶颈在于IO而不是并发。将复杂的查询拆分成简单的数据库查询可以极大地提高缓存利用率,降低磁盘IO。但是Django延迟载入关联实体在实际情况下性能如何我没有考证过。

这里值得注意的是,Django在实现数据模型层的时候应该是用到了python语言本身扩展自己语法的特性。因为它直接使用了python的切片语法来实现sql的limit操作。如 users.objects.all()[0:5],在Django文档中说明了all()操作会造成数据库访问,如果没有对语法进行扩展的话,那么切片时岂不是已经对数据库进行了全表查询?

2.对查询结果的数据缓存。

对普通的数据查询来说,Djang没有提供特别的缓存方式,需要用户手工用变量来缓存上次查询的结果。对于关联数据,如果执行了select_related()或者prefetch_related(),那么通过self来读取关联实体时读取的是缓存。

3.模型的继承。

Django提供了三种继承方式,php的Doctrine也实现了类似的方式。三种继承分别是:“继承自抽象父类”,“继承自普通数据模型”,“继承变成代理”。具体意义分别是:“抽象父类只包括通用属性或者方法,本身不能生成表”;“继承后的模型对自己的特有字段生成新表”;“继承后的模型不生成新表,只是一个可以复写源模型行为的代理”。

 

总结:

1.关于ORM感觉已经没有太多值得讨论的了,请看优快云范凯的 《WEB的缓存设计模式》。

2.数据层以及持久化的具体实现其实不需要纠结,目前的ORM已经足够强大,真正纠结的是业务逻辑造成的数据模型关联。也是我开篇一堆废话所说的。

3.Django数据模型层对python本身特性的使用让我很感兴趣,这在php中是没有的。下一篇准备研究python扩展自身的能力。

4.NOSQL将如何改变框架中的数据模型层?我认为没有太大改变,如上所说,数据库如何变化说到底只是数据如何持久化。框架始终关注的是如何更好的表现业务逻辑。

转载于:https://www.cnblogs.com/sskyy/archive/2013/03/12/2955929.html

资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值