orator, Orator提供了一个简单但美观的ActiveRecord实现

分享于 

22分钟阅读

GitHub

  繁體 雙語
The Orator ORM provides a simple yet beautiful ActiveRecord implementation.
  • 源代码名称:orator
  • 源代码网址:http://www.github.com/sdispater/orator
  • orator源代码文档
  • orator源代码下载
  • Git URL:
    git://www.github.com/sdispater/orator.git
    Git Clone代码到本地:
    git clone http://www.github.com/sdispater/orator
    Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/sdispater/orator
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    
    Orator Orator Build status

    Orator提供了一个简单但美观的ActiveRecord实现。

    它受到 Laravel 框架的数据库部分的启发,但是大部分被修改为更高的效率。

    这里提供完整的文档: http://orator-orm.com/docs

    安装

    你可以用 2种不同的方式安装 Orator:

    • 更简单更简单的方法是使用 pip
    pip install orator

    不同dbapi软件包不是软件包依赖项的一部分,因此必须安装它们才能连接到相应的数据库:

    • Postgres: psycopg2
    • MySQL: PyMySQL 或者 mysqlclient
    • SQLite: 默认情况下,sqlite3 MODULE 与 python 捆绑在一起

    基本用法

    配置

    要启动你的数据库连接并将它的传递到 DatabaseManager 实例,你所需要的就是配置。

    from orator import DatabaseManager, Model
    config = {
     'mysql': {
     'driver': 'mysql',
     'host': 'localhost',
     'database': 'database',
     'user': 'root',
     'password': '',
     'prefix': '' }
    }
    db = DatabaseManager(config)
    Model.set_connection_resolver(db)

    定义模型

    classUser(Model):
     pass

    注意,我们没有告诉ORM哪一个表应该用于 User 模型。 除非显式指定了另一个 NAME,否则类 NAME的复数"snake案例"NAME 将用作表 NAME。 在这种情况下,ORM将假定 User 模型在 users 表中存储记录。 你可以通过在模型上定义 __table__ 属性来指定自定义表:

    classUser(Model):
     __table__ ='my_users'

    ORM还将假定每个表都有一个名为 id的主键列。 你可以定义一个 __primary_key__ 属性来替代这里约定。 这里类似,可以定义 __connection__ 属性来重写使用模型时应该使用的数据库连接的NAME。

    定义模型后,就可以开始在表中检索和创建记录了。 注意,默认情况下,你需要将 updated_atcreated_at 列放在表。 如果不希望自动维护这些列,请将模型上的__timestamps__ 属性设置为 False

    检索所有模型

    users = User.all()

    按主键检索记录

    user = User.find(1)print(user.name)

    使用模型的查询

    users = User.where('votes', '>', 100).take(10).get()for user in users:
     print(user.name)

    聚合

    你还可以使用查询生成器聚合函数:

    count = User.where('votes', '>', 100).count()

    如果你觉得受生成器接口的流利限制,可以使用 where_raw 方法:

    users = User.where_raw('age>? and votes = 100', [25]).get()

    块结果

    如果需要处理大量记录,可以使用 chunk 方法来避免消耗大量内存:

    for users in User.chunk(100):
     for user in users:
     #.. .

    指定查询连接

    使用 on 方法查询模型时,可以指定要使用的数据库连接:

    user = User.on('connection-name').find(1)

    如果使用读/写连接,则可以强制查询使用与以下方法相同的"写入"连接:

    user = User.on_write_connection().find(1)

    三维质量分配

    创建新模型时,将属性传递给模型构造函数。 这些属性然后通过质量分配分配给模型。 如果用户输入模型中的用户输入,但这可能会带来严重的安全问题,因为用户可以随意修改模型的所有属性的英镑和英镑的收费。 由于这个原因,所有的模型在默认情况下都。

    开始时,请在模型中设置 __fillable__ 或者 __guarded__ 属性。

    定义模型上的可以填充属性

    __fillable__ 属性指定可以指定的属性。

    classUser(Model):
     __fillable__ = ['first_name', 'last_name', 'email']

    定义模型上的受保护属性

    __guarded__ 是反向的,充当"黑名单"。

    classUser(Model):
     __guarded__ = ['id', 'password']

    你还可以从质量分配中阻止所有属性的

    __guarded__ = ['*']

    插入,更新和删除

    保存新模型

    创建新的记录,只需创建一个新的模型实例并调用 save 方法。

    user = User()
    user.name ='John'user.save()

    你也可以使用 create 方法保存模型,但是你需要在模型中指定 __fillable__ 或者 __guarded__ 属性,因为默认情况下,所有模型都是针对质量分配的。

    使用自动递增ID保存或者创建新模型后,可以通过访问对象属性的id 来检索该标识:

    inserted_id = user.id

    使用创建方法

    # Create a new user in the databaseuser = User.create(name='John')# Retrieve the user by attributes, or create it if it does not existuser = User.first_or_create(name='John')# Retrieve the user by attributes, or instantiate it if it does not existuser = User.first_or_new(name='John')

    更新检索到的模型

    user = User.find(1)
    user.name ='Foo'user.save()

    你还可以根据对一组模型的查询来运行更新:

    affected_rows = User.where('votes', '>', 100).update(status=2)

    删除现有模型

    若要删除模型,只需调用 delete 模型:

    user = User.find(1)
    user.delete()

    按键删除现有模型

    User.destroy(1)
    User.destroy(1, 2, 3)

    你还可以在一组模型上运行删除查询:

    affected_rows = User.where('votes', '>'100).delete()

    只更新模型的时间戳

    如果只需要更新模型的时间戳,则可以使用 touch 方法:

    user.touch()

    时间戳

    默认情况下,ORM将自动在数据库表中维护 created_atupdated_at 列。 只需将这些 timestamp 列添加到。 如果你不希望ORM维护这些列,只需添加 __timestamps__ 属性:

    classUser(Model):
     __timestamps__ =False

    提供自定义时间戳格式

    如果希望自定义使用 to_dict 或者 to_json 方法返回的时间戳( 默认为ISO格式)的格式,则可以重写 get_date_format 方法:

    classUser(Model):
     defget_date_format():
     return'DD-MM-YY'

    转换为字典/json

    将模型转换为字典

    构建 JSON api时,通常需要将模型和关系转换为字典或者 JSON。 因此,Orator包含了这样做的方法。 要将模型及其加载的关系转换为字典,可以使用 to_dict 方法:

    user = User.with_('roles').first()return user.to_dict()

    注意,模型的整个集合也可以转换为字典:

    return User.all().serailize()

    将模型转换为 JSON

    若要将模型转换为 JSON,可以使用 to_json 方法 !

    return User.find(1).to_json()

    查询生成器

    简介

    数据库查询生成器提供了一个连贯的接口来创建和运行数据库查询。 它可以用于在应用程序中执行大多数数据库操作,并在所有受支持的数据库系统。

    选择

    从表中检索所有行
    users = db.table('users').get()for user in users:
     print(user['name'])
    表的块结果
    for users in db.table('users').chunk(100):
     for user in users:
     #.. .
    从表中检索单个行的
    user = db.table('users').where('name', 'John').first()print(user['name'])
    从一行检索单个列
    user = db.table('users').where('name', 'John').pluck('name')
    检索列值的列表
    roles = db.table('roles').lists('title')

    这里方法将返回角色标题的列表。 如果你传递额外的关键参数,它可以返回字典。

    roles = db.table('roles').lists('title', 'name')
    指定一个选择子句
    users = db.table('users').select('name', 'email').get()
    users = db.table('users').distinct().get()
    users = db.table('users').select('name as user_name').get()
    在现有查询中添加选择子句
    query = db.table('users').select('name')
    users = query.add_select('age').get()
    使用运算符的
    users = db.table('users').where('age', '>', 25).get()
    或者语句
    users = db.table('users').where('age', '>', 25).or_where('name', 'John').get()
    使用
    users = db.table('users').where_between('age', [25, 35]).get()
    使用不在之间的where
    users = db.table('users').where_not_between('age', [25, 35]).get()
    使用在
    users = db.table('users').where_in('id', [1, 2, 3]).get()
    users = db.table('users').where_not_in('id', [1, 2, 3]).get()
    使用Null来查找具有空值的记录的
    users = db.table('users').where_null('updated_at').get()
    ORDER BY,GROUP BY 和 Having
    query = db.table('users').order_by('name', 'desc')
    query = query.group_by('count')
    query = query.having('count', '>', 100)
    users = query.get()
    偏移和限制
    users = db.table('users').skip(10).take(5).get()
    users = db.table('users').offset(10).limit(5).get()

    连接

    查询生成器还可以用于编写 Join 语句。

    Basic基本的语句
    db.table('users') 
    . join('contacts', 'users.id', '=', 'contacts.user_id') 
    . join('orders', 'users.id', '=', 'orders.user_id') 
    . select('users.id', 'contacts.phone', 'orders.price') 
    . get()
    db.table('users').left_join('posts', 'users.id', '=', 'posts.user_id').get()

    你还可以指定更高级的Join 子句:

    clause = JoinClause('contacts').on('users.id', '=', 'contacts.user_id').or_on(...)
    db.table('users').join(clause).get()

    如果想在连接中使用"位置"样式子句,可以在 Join 中使用 whereor_where 方法。 这些方法将比较列与值,而不是比较两个列:

    clause = JoinClause('contacts').on('users.id', '=', 'contacts.user_id').where('contacts.user_id', '>', 5)
    db.table('users').join(clause).get()

    在那里

    有时你可能需要创建更高级的where子句,比如"存在位置"或者嵌套参数分组。 使用Orator查询生成器是相当容易

    参数组
    db.table('users') 
    . where('name', '=', 'John') 
    . or_where(
     db.query().where('votes', '>', 100).where('title', '!=', 'admin')
     ).get()

    上面的查询将生成以下 SQL:

    SELECT*FROM users WHERE name ='John'OR (votes >100AND title !='Admin')
    存在语句
    db.table('users').where_exists(
     db.table('orders').select(db.raw(1)).where_raw('order.user_id = users.id')
    )

    上面的查询将生成以下 SQL:

    SELECT*FROM usersWHERE EXISTS (
     SELECT1FROM orders WHEREorders.user_id=users.id)

    聚合

    还提供了各种聚合方法,如 countmaxminavgsum

    users = db.table('users').count()
    price = db.table('orders').max('price')
    price = db.table('orders').min('price')
    price = db.table('orders').avg('price')
    total = db.table('users').sum('votes')

    原始表达式

    有时你可能需要在查询中使用原始表达式。 这些表达式将作为字符串注入到查询中,因此请注意不要创建任何 SQL注入 点 ! 若要创建原始表达式,可以使用 raw() 方法:

    db.table('users') 
    . select(db.raw('count(*) as user_count, status')) 
    . where('status', '!=', 1) 
    . group_by('status') 
    . get()

    插入

    将记录插入表中
    db.table('users').insert(email='foo@bar.com', votes=0)
    db.table('users').insert({
     'email': 'foo@bar.com',
     'votes': 0})

    重要的是要注意,有两个符号可用。 原因很简单: 字典表示法虽然有点不实用,但是处理不能作为关键字参数传递的列名。

    将记录插入具有自动递增标识的表中

    如果表具有自动递增的标识,请使用 insert_get_id 插入记录并检索 id:

    id= db.table('users').insert_get_id({
     'email': 'foo@bar.com',
     'votes': 0})
    将多个记录插入表中
    db.table('users').insert([
     {'email': 'foo@bar.com', 'votes': 0},
     {'email': 'bar@baz.com', 'votes': 0}
    ])

    更新

    更新记录
    db.table('users').where('id', 1).update(votes=1)
    db.table('users').where('id', 1).update({'votes': 1})

    insert 语句一样,有两个可用的符号。 原因很简单: 字典表示法虽然有点不实用,但是处理不能作为关键字参数传递的列名。

    Incrementing递增或者递减列的值
    db.table('users').increment('votes') # Increment the value by 1db.table('users').increment('votes', 5) # Increment the value by 5db.table('users').decrement('votes') # Decrement the value by 1db.table('users').decrement('votes', 5) # Decrement the value by 5

    你还可以指定要更新的其他列:

    db.table('users').increment('votes', 1, name='John')

    删除

    删除记录
    db.table('users').where('age', '<', 25).delete()
    删除所有记录
    db.table('users').delete()
    截断
    db.table('users').truncate()

    联合

    查询生成器提供了一个快速而简单的方法来"并集"两个查询:

    first = db.table('users').where_null('first_name')
    users = db.table('users').where_null('last_name').union(first).get()

    union_all 方法也可用。

    读/写连接

    有时,你可能希望对SELECT语句使用一个数据库连接,而对于 INSERT。UPDATE和DELETE语句则使用另一个数据库连接。 使用原始查询。查询生成器或者实际的ORM,Orator将使这一点变得容易。

    下面是应该如何配置读/写连接的示例:

    config = {
     'mysql': {
     'read': {
     'host': '192.168.1.1' },
     'write': {
     'host': '192.168.1.2' },
     'driver': 'mysql',
     'database': 'database',
     'user': 'root',
     'password': '',
     'prefix': '' }
    }

    请注意,配置字典中已经添加了两个键: readwrite。这两个键都有包含单个键的字典值: hostreadwrite 连接的数据库选项的其余部分将从主 mysql 字典中合并。 因此,如果你希望覆盖主字典中的值,你只需要在 readwrite 字典中放置条目。 在这种情况下,192.168.1.1 将用作"读取"连接,而 192.168.1.2 将用作"写入"连接。 主 mysql 字典中的数据库凭据。前缀。字符集和所有其他选项都将在两个连接中共享。

    数据库事务

    若要在数据库事务中运行一组操作,可以使用 transaction 方法,该方法是上下文管理器:

    with db.transaction():
     db.table('users').update({votes: 1})
     db.table('posts').delete()

    便笺

    事务块中引发的任何异常都将导致自动回滚事务。

    有时你可能需要自己启动事务:

    db.begin_transaction()

    你可以使用 rollback 方法回滚事务:

    db.rollback()

    你还可以通过 commit 方法提交事务:

    db.commit()

    默认情况下,所有基础DBAPI连接都设置为自动提交模式,意味着不需要在每次操作之后显式提交。

    访问连接

    使用多个连接时,可以通过 connection() 方法访问它们:

    users = db.connection('foo').table('users').get()

    你还可以访问原始的,底层的dbapi连接实例:

    db.connection().get_connection()

    有时,你可能需要重新连接到给定的数据库:

    db.reconnect('foo')

    如果需要断开与给定数据库的连接,请使用 disconnect 方法:

    db.disconnect('foo')

    IMP  Implementation  act  bea  Active  ORM  
    相关文章