" 让事情变得尽可能简单,但并不简单. "
我们能找到修复Python数据库世界的解决方案吗?
更新:Alex Martelli编写了一个'lustdb'原型 - 如果你知道任何有多个后端的轻量级,高级数据库库,我们可以包含语法糖蜂蜜,请称重!
from someAmazingDB import * #we imported a smart model class and db object which talk to database adapter/s class Task (model): title = '' done = False #native types not a custom object we have to think about! db.taskList = [] #or db.taskList = expandableTypeCollection(Task) #not sure what this syntax would be db['taskList'].append(Task(title='Beat old sql interfaces',done=False)) db.taskList.append(Task('Illustrate different syntax modes',True)) # ok maybe we should just use kwargs #at this point it should be autosaved to a default db option #by default we should be able to reload the console and access the default db: >> from someAmazingDB import * >> print 'Done tasks:' >> for task in db.taskList: >> if task.done: >> print task.title 'Illustrate different syntax modes'
我是Python,webPy和Cherry Py以及KISS的粉丝.
我们正在谈论自动 Python到SQL 类型转换或NoSQL. 我们不必完全兼容SQL!只是一个可扩展的子集或忽略它!
Re:模型更改,可以询问开发人员何时尝试更改它或具有一组合理的默认值.
这是一个挑战:上面的代码应该只需要很少的修改或思考.当我们知道更好的时候,为什么我们必须忍受妥协呢?
在2010年,我们应该能够在睡眠中编写可扩展的简单数据库.
如果你认为这很重要,请upvote!
您要求的内容无法在Python 2中完成.无论如何,出于非常具体的原因.你想写:
class Task(model): title = '' isDone = False
在Python 2,什么,什么 model
可能是,这不能永远让你预测这两个领域的任何"订货",因为语义class
声明如下:
执行身体,从而准备一个 dict
找到元类并运行其特殊方法
无论元类可能是什么,第1步都破坏了字段顺序的任何可预测性.
因此,您需要使用位置参数,在代码段中:
Task('Illustrate different syntax modes', True)
不能将参数的值与模型的各个字段相关联.(试图通过类型关联来猜测 - 希望没有两个领域具有相同的类型 - 将比你表达的使用db.tasklist
和db['tasklist']
无差别且可互换的愿望更加可怕.
Python 3中的一个向后不兼容的更改是专门为处理此类情况而引入的.在Python 3中,自定义元类可以定义一个在上面的简化列表中"步骤1" 之前__prepare__
运行的函数,这使它可以更好地控制类的主体.具体来说,引用PEP 3115 ...:
__prepare__
返回一个类似字典的对象,用于在评估类体时存储类成员定义.换句话说,类主体被评估为一个功能块(就像它现在一样),除了局部变量字典被返回的字典替换__prepare__
.该字典对象可以是常规字典或自定义映射类型.
...
一个示例是一个元类,它使用有关成员声明排序的信息来创建C结构.元类将提供一个自定义字典,只需记录插入顺序.
你不想像在这个例子中那样"创建一个C结构",但是字段的顺序是至关重要的(允许使用你想要的位置参数),所以自定义元类(通过base获得model
)会有一个__prepare__
类方法返回有序字典.这消除了特定的问题,但是,当然,只有当您愿意使用这个"神奇的ORM"将所有代码切换到Python 3.您会是吗?
一旦确定,问题是,您想要执行什么数据库操作,以及如何执行.当然,你的例子根本没有说明这一点.是taskList
属性名称特殊,或应任何分配给其他的属性,db
对象是"自动保存"(通过名称和,还有什么其他特点[S])和"autoretrieved"在使用?有没有办法删除实体,改变它们,找到它们(除了曾经被列在db
对象的同一属性中)?如果需要身份验证,您的示例代码如何知道要使用的数据库服务以及如何对其进行身份验证(例如,通过用户标识和密码)?
您列出的具体任务并不难实现(例如,在Google App Engine的存储服务之上,它不需要身份验证,也不需要指定"使用什么数据库服务"). model
的元类会反省类的字段并Model
为类生成一个GAE ,该db
对象将用于__setattr__
设置atexit
触发器来存储属性的最终值(Model
当然是一个不同类型的实体),并__getattr__
获取该属性的从存储中恢复的信息.当然,如果没有一些额外的数据库功能,这一切都将毫无用处;-).
编辑:所以我做了一个小原型(Python 2.6,基于sqlite)并把它放在http://www.aleax.it/lustdb.zip上 - 这是一个包含225行的3K zipfile lustdb.py
(太长了,无法发布)这里)两个小的测试文件大致相当于OP的原件:test0.py
是......:
from lustdb import * class Task(Model): title = '' done = False db.taskList = [] db.taskList.append(Task(title='Beat old sql interfaces', done=False)) db.taskList.append(Task(title='Illustrate different syntax modes', done=True))
并且test1.p1
......:
from lustdb import * print 'Done tasks:' for task in db.taskList: if task.done: print task
运行test0.py
(在具有可写/tmp
目录的计算机上- 即任何Unix-y操作系统,或者在Windows上,mkdir \tmp
以前任何时间运行过的操作系统;-)没有输出; 之后,运行test1.py
输出:
Done tasks: Task(done=True, title=u'Illustrate different syntax modes')
请注意,这些在很多方面都比OP的例子要小得多"疯狂",例如...:
1. no (expletive delete) redundancy whereby `db.taskList` is a synonym of `db['taskList']`, only the sensible former syntax (attribute-access) is supported 2. no mysterious (and totally crazy) way whereby a `done` attribute magically becomes `isDone` instead midway through the code 3. no mysterious (and utterly batty) way whereby a `print task` arbitrarily (or magically?) picks and prints just one of the attributes of the task 4. no weird gyrations and incantations to allow positional-attributes in lieu of named ones (this one the OP agreed to)
当然原型(原型将;-)在许多方面都有很多不足之处(清晰度,文档,单元测试,优化,错误检查和诊断,不同后端之间的可移植性,尤其是除了隐含的那些之外的数据库功能)问题).缺少的数据库功能很多(例如,OP的原始示例无法识别模型的"主键"或任何其他类型的唯一性约束,因此重复数据可能比比皆是;并且只会从那里变得更糟; - ).尽管如此,对于225行(190行空行,评论和文档字符串;-),我的偏见并不是太糟糕.
继续玩这个项目的正确方法当然是lustdb
在code.google.com的托管部分(或任何其他良好的开源托管网站上启动一个新的开源项目,包括问题跟踪器,维基,代码评论支持,在线浏览,DVCS支持等等) - 我自己做,但我在code.google.com上可以启动的开源项目数量接近极限,不想"刻录"以这种方式最后一两个;-).
BTW,该lustdb
模块的名称是OP的首字母(前后两个字母的首字母和姓氏),在传统awk
和朋友的传统- 我认为听起来很好(和大多数其他明显的名称,如simpledb
和dumbdb
被采取;-).