pony.orm基础入门

什么是Pony ORM

Pony是一个高级的对象关系映射器。ORM允许开发人员以对象的形式来处理数据库的内容。一个关系型数据库包含的是存储在表中的行。然而,当用高级的面向对象语言编写程序时,当从数据库中检索的数据可以以对象的形式访问时,就会方便很多。Pony ORM是Python语言的一个库,可以方便地处理以行形式存储在关系型数据库中的对象。

  • 优点
    编写查询的语法特别方便
    自动查询优化
    自动创建数据表

安装

pip install pony

导入

from pony.orm import *

这将导入使用Pony所需的整个(而不是非常大)的类和函数集。最终您可以选择要导入的内容,但我们建议您首先使用import * ,或者仅导入所需:

from pony.orm import (Json, PrimaryKey, Required, db_session, select, desc, Set, get, Optional, Database)

创建数据库对象

  • 方法一、创建空的数据连接然后绑定

db = Database()
空的连接往往是更方便做后期使用DB()方法。这样你就可以使用不同的数据库进行测试和制作。
然后进行绑定,支持多种数据库db.bind()
postgres:db.bind('postgres', user='', password='', host='', database='')
mysql:db.bind('mysql', host='', user='', passwd='', db='')
oracle:db.bind('oracle', 'user/password@dsn')
sqlite:db.bind('sqlite', 'filename', create_db=True) create_db:如果数据库不存在创建数据库文件

  • 方法二、通过参数连接

db = Database("mysql", host="localhost",
user="root",
passwd="123123",
db="t2")
代码示例

from pony.orm import Database
import os
import logging
from pony.orm import (Json, PrimaryKey, Required, db_session, select, desc, Set, get, Optional)
'''
Pony规定与数据库进行交互的代码必须在数据库会话中工作
可以使用@db_session装修或db_session上下文管理数据库的工作。
当会话结束时,它会做以下操作
提交事务或则回滚事务。
返回连接池的数据库连接。
清除缓存。
'''
# logging.basicConfig(level=logging.DEBUG,format='%(asctime)s::%(message)s::%(levelname)s::%(args)s')

db = Database(provider = "mysql",
              host = os.getenv('HOST') if os.getenv('MY_HOST') else '10.1.1.1',
              port = int(os.getenv('Port')) or 3307,
              user = os.getenv('USER') if os.getenv('MY_USER') else 'root',
              password = os.getenv('PASSWORD') or '1256',
              database = os.getenv('DB') or 'message_center'
              )

定义实体

凡继承Database.Entity的类都是实体类,实体类实例存储在数据库中,该数据库绑定到db变量。
例:class Content(db.Entity)

属性

class Info(db.Entity):
    _table_ = 'info'
    id = PrimaryKey(int, auto = True) #autoBoolean 是否自增
    key = Required(str, 50)
    name = Required(str, 30, default = "未知") #如果是必须的话必须加默认值
    url = Optional(str, 100)
    comment = Optional(str, 50, nullable = True)
    create_time = Required(datetime.datetime, default = datetime.datetime.now(), nullable = True)
    update_time = Optional(datetime.datetime)
    type = Required(str, 50)
    isdelete = Optional(bool)

属性类型分:Required(必选)、Optional(可选)、PrimaryKey(主键)、Set

Set

定义了一对一,一对多,多对多等数据结构

classStudent(db.Entity):

    name = Required(str)

   courses =Set("Course")
classCourse(db.Entity):

    name=Required(str)

    semester =Required(int)

    students =Set(Student)

     PrimaryKey(name, semester)

属性数据类型

格式为:属性名 = 属性类型(数据类型)
str
unicode
int
float
Decimal
datetime
date
time
timedelta
bool
buffer - used for binary data in Python 2 and 3
bytes - used for binary data in Python 3
LongStr - used for large strings
LongUnicode - used for large strings
UUID

属性参数

字符串长度 默认为255
name = Required(str,40)# VARCHAR(40)
整数的大小 默认32bit INTEGER
attr1 = Required(int,size=8) #8bit - TINYINTinMySQL
attr5 = Required(int,size=64) #64bit - BIGINTinMySQL
无符号
attr1 = Required(int, size=8,unsigned=True)# TINYINT UNSIGNEDinMySQL
小数和精度
price = Required(Decimal,10,2)# DECIMAL(10, 2)
时间
dt = Required(datetime, 6)
其他的参数
unique
Boolean 是否唯一
auto
Boolean 是否自增
default
默认值
sql_default
created_at = Required(datetime, sql_default=’CURRENT_TIMESTAMP’)
index
index=True创建的默认索引名称
index=’index_name’指定索引名称.
reverse
Specifies the attribute at the other end which should be used for the relationship.
reverse_column
Used for a symmetric relationship in order to specify the name of the database column for the intermediate table.
reverse_columns
Used for a symmetric relationship if the entity has a composite primary key. Allows you to specify the name of the database columns for the intermediate table.
table
多对多中间表的表名
nullable
允许该列为数据库中的空

将实体映射到数据库表

创建表,实体类的映射关系,这种映射关系非常重要,pony在启动项目时会检查整个项目的所有实体类的映射关系是否正确。为此,我们需要在Database对象上调用generate_mapping()方法:

db.generate_mapping(create_tables=True)

import connexion
from database.mysql_conn import db
from database.db_info import Info
from database.db_content import Content


if __name__ == '__main__':

    db.generate_mapping(create_tables=True)  # 创建表,实体类的映射关系,这种映射关系非常重要,pony在启动项目时会检查整个项目的所有实体类的映射关系是否正确。

参数create_tables = True表示如果实体指向的表尚不存在,则使用CREATE TABLE命令创建它们。必须在调用generate_mapping()方法之前定义连接到数据库的所有实体。

注:仅调用一次,且调用的的py文件必须import全部实体的类,否则报错pony.orm.core.ERDiagramError: Cannot define entity 'Content': database mapping has already been generated

实例

每个实例对应于数据库表中的一行

Content(msgtype=msgtype, name=name, content=content, project=project, sprint=sprint, create_time=datetime.datetime.now(), isdelete=0)

会话

Pony规定与数据库进行交互的代码必须在数据库会话中工作可以使用@ db_session装修,当会话结束时,它会做以下操作:

  • 如果函数引发异常,则执行事务回滚
  • 如果数据已更改且未发生异常,则提交事务
  • 返回连接池的数据库连接
  • 清除数据库会话缓存
    @classmethod
    @db_session
    def db_create_content(cls, msgtype, name, content):
        obj = get(n for n in Content if n.name == name)
        if obj:
            raise IsExist(title='该名字的模版已经存在', detail=f'name为【{name}】的模版已经存在')
        else:
            Content(msgtype=msgtype, name=name, content=str(content), create_time=datetime.datetime.now(), isdelete=0)

查询

要对结果列表进行排序,可以使用Query.order_by()方法。如果只需要结果集的一部分,则可以使用切片运算符,与在Python列表上执行的操作完全相同。例如,如果要按名称对所有人进行排序并提取前两个对象,则可以这样做:

select(pforpinPerson).order_by(Person.name)
select(n for n in Content if n.isdelete==0)

获取对象

要通过主键获取对象,您需要在方括号中指定主键值:
p1 = Person[1]
print p1.name

    @classmethod
    @db_session
    def db_get_content(cls):
        objs = select(n for n in Content if n.isdelete==0)
        data = []
        for obj in objs:
            dict = {
                "name": obj.name,
                "content": obj.content,
                "msgtype": obj.msgtype,
                # "project": obj.project,
                # "sprint": obj.sprint
            }
            data.append(dict)
        return data

您可能会注意到没有向数据库发送任何查询。发生这种情况是因为此对象已存在于数据库会话高速缓存中。缓存减少了需要发送到数据库的请求数。

要通过其他属性检索对象,可以使用Entity.get()方法:
mary = Person.get(name='Mary')
在这种情况下,即使对象已经加载到缓存中,仍然必须将查询发送到数据库,因为name属性不是唯一键。仅当我们通过主键或唯一键查找对象时,才会使用数据库会话高速缓存。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353