未加星标

详解python的ORM中Pony用法

字体大小 | |
[开发(python) 所属分类 开发(python) | 发布者 店小二04 | 时间 | 作者 红领巾 ] 0人收藏点击收藏

Pony是python的一种ORM,它允许使用生成器表达式来构造查询,通过将生成器表达式的抽象语法树解析成SQL语句。它也有在线ER图编辑器可以帮助你创建Model。

示例分析

Pony语句:

select(p for p in Person if p.age > 20)

翻译成sql语句就是:

SELECT p.id, p.name, p.age, p.classtype, p.mentor, p.gpa, p.degree
FROM person p
WHERE p.classtype IN ('Student', 'Professor', 'Person')
AND p.age > 20

Pony语句:

select(c for c in Customer
if sum(c.orders.price) > 1000)

翻译成sql语句就是:

SELECT "c"."id"
FROM "Customer" "c"
LEFT JOIN "Order" "order-1"
ON "c"."id" = "order-1"."customer"
GROUP BY "c"."id"
HAVING coalesce(SUM("order-1"."total_price"), 0) > 1000

安装Pony

pip install pony

使用Pony

#!/usr/bin/env python
#-*- coding:utf-8 -*-
import datetime
import pony.orm as pny
import sqlite3
# conn = sqlite3.connect('D:\日常python学习PY2\Pony学习\music.sqlite')
# print conn
# database = pny.Database()
# database.bind("sqlite","music.sqlite",create_db=True)
# 路径建议写绝对路径。我这边开始写相对路径报错 unable to open database file
database = pny.Database("sqlite","D:\日常python学习PY2\Pony学习\music.sqlite",create_db=True)
########################################################################
class Artist(database.Entity):
"""
Pony ORM model of the Artist table
"""
name = pny.Required(unicode)
#被外键关联
albums = pny.Set("Album")
########################################################################
class Album(database.Entity):
"""
Pony ORM model of album table
"""
#外键字段artlist,外键关联表Artist,Artist表必须写Set表示被外键关联
#这个外键字段默认就是index=True,除非自己指定index=False才不会创建索引,索引名默认为[idx_表名__字段](artist)
artist = pny.Required(Artist)
title = pny.Required(unicode)
release_date = pny.Required(datetime.date)
publisher = pny.Required(unicode)
media_type = pny.Required(unicode)
# turn on debug mode
pny.sql_debug(True) # 显示debug信息(sql语句)
# map the models to the database
# and create the tables, if they don't exist
database.generate_mapping(create_tables=True) # 如果数据库表没有创建表

运行之后生成sqlite如下:

上述代码对应的sqlite语句是:

GET CONNECTION FROM THE LOCAL POOL
PRAGMA foreign_keys = false
BEGIN IMMEDIATE TRANSACTION
CREATE TABLE "Artist" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"name" TEXT NOT NULL
)

CREATE TABLE "Album" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"artist" INTEGER NOT NULL REFERENCES "Artist" ("id"),
"title" TEXT NOT NULL,
"release_date" DATE NOT NULL,
"publisher" TEXT NOT NULL,
"media_type" TEXT NOT NULL
)

CREATE INDEX "idx_album__artist" ON "Album" ("artist")

SELECT "Album"."id", "Album"."artist", "Album"."title", "Album"."release_date", "Album"."publisher", "Album"."media_type"
FROM "Album" "Album"
WHERE 0 = 1

SELECT "Artist"."id", "Artist"."name"
FROM "Artist" "Artist"
WHERE 0 = 1

COMMIT
PRAGMA foreign_keys = true
CLOSE CONNECTION

插入/增加数据

源码地址:https://github.com/flowpig/daily_demos

#!/usr/bin/env python
#-*- coding:utf-8 -*-
import datetime
import pony.orm as pny
from models import Album, Artist
from database import PonyDatabase
# ----------------------------------------------------------------------
@pny.db_session
def add_data():
""""""
new_artist = Artist(name=u"Newsboys")
bands = [u"MXPX", u"Kutless", u"Thousand Foot Krutch"]
for band in bands:
artist = Artist(name=band)
album = Album(artist=new_artist,
title=u"Read All About It",
release_date=datetime.date(1988, 12, 01),
publisher=u"Refuge",
media_type=u"CD")
albums = [{"artist": new_artist,
"title": "Hell is for Wimps",
"release_date": datetime.date(1990, 07, 31),
"publisher": "Sparrow",
"media_type": "CD"
},
{"artist": new_artist,
"title": "Love Liberty Disco",
"release_date": datetime.date(1999, 11, 16),
"publisher": "Sparrow",
"media_type": "CD"
},
{"artist": new_artist,
"title": "Thrive",
"release_date": datetime.date(2002, 03, 26),
"publisher": "Sparrow",
"media_type": "CD"}
]
for album in albums:
a = Album(**album)
if __name__ == "__main__":
db = PonyDatabase()
db.bind("sqlite", "D:\日常python学习PY2\Pony学习\music.sqlite", create_db=True)
db.generate_mapping(create_tables=True)
add_data()
# use db_session as a context manager
with pny.db_session:
a = Artist(name="Skillet")
'''
您会注意到我们需要使用一个装饰器db_session来处理数据库。
它负责打开连接,提交数据并关闭连接。 你也可以把它作为一个上
下文管理器,with pny.db_session
'''

更新数据

#!/usr/bin/env python
#-*- coding:utf-8 -*-
import pony.orm as pny
from models import Artist, Album
from database import PonyDatabase
db = PonyDatabase()
db.bind("sqlite", "D:\日常python学习PY2\Pony学习\music.sqlite", create_db=True)
db.generate_mapping(create_tables=True)
with pny.db_session:
band = Artist.get(name="Newsboys")
print band.name
for record in band.albums:
print record.title
# update a record
band_name = Artist.get(name="Kutless")
band_name.name = "Beach Boys"

#使用生成器形式查询
'''
result = pny.select(i.name for i in Artist)
result.show()

结果:
i.name
--------------------
Newsboys
MXPX
Beach Boys
Thousand Foot Krutch
Skillet
'''

删除记录

import pony.orm as pny
from models import Artist
with pny.db_session:
band = Artist.get(name="MXPX")
band.delete()

Pony补充

可以连接的数据库:

##postgres
db.bind('postgres', user='', password='', host='', database='')
##sqlite create_db:如果数据库不存在创建数据库文件
db.bind('sqlite', 'filename', create_db=True)
##mysql
db.bind('mysql', host='', user='', passwd='', db='')
##Oracle
db.bind('oracle', 'user/[email protected]')

Entity(实体)类似mvc里面的model

在创建实体实例之前,需要将实体映射到数据库表,生成映射后,可以通过实体查询数据库并创建新的实例。db.Entity自己定义新的实体必须从db.Entity继承

属性

class Customer(db.Entity):
name = Required(str)
picture = Optional(buffer)
sql_debug(True) # 显示debug信息(sql语句)
db.generate_mapping(create_tables=True) # 如果数据库表没有创建表

属性类型

Required
Optional
PrimaryKey
Set

Required and Optional

通常实体属性分为Required(必选)和Optional(可选)

PrimaryKey(主键)

默认每个实体都有一个主键,默认添加了id=PrimaryKey(int,auto=True)属性

class Product(db.Entity):
name = Required(str, unique=True)
price = Required(Decimal)
description = Optional(str)

#等价于下面
class Product(db.Entity):
id = PrimaryKey(int, auto=True)
name = Required(str, unique=True)
price = Required(Decimal)
description = Optional(str)

Set

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

# 一对一
class User(db.Entity):
name = Required(str)
cart = Optional("Cart") #必须Optional-Required or Optional-Optional
class Cart(db.Entity):
user = Required("User")

# 多对多
class Student(db.Entity):
name = pny.Required(str)
courses = pny.Set("Course")
class Course(db.Entity):
name = pny.Required(str)
semester = pny.Required(int)
students = pny.Set(Student)
pny.PrimaryKey(name, semester) #联合主键
pny.sql_debug(True) # 显示debug信息(sql语句)
db.generate_mapping(create_tables=True) # 如果数据库表没有创建表
#-------------------------------------------------------
#一对多
class Artist(database.Entity):
"""
Pony ORM model of the Artist table
"""
name = pny.Required(unicode)
#被外键关联
albums = pny.Set("Album")
class Album(database.Entity):
"""
Pony ORM model of album table
"""
#外键字段artlist,外键关联表Artist,Artist表必须写Set表示被外键关联
#这个外键字段默认就是index=True,除非自己指定index=False才不会创建索引,索引名默认为[idx_表名__字段](artist)
artist = pny.Required(Artist) #外键字段(数据库显示artist)
title = pny.Required(unicode)
release_date = pny.Required(datetime.date)
publisher = pny.Required(unicode)
media_type = pny.Required(unicode)
# Compositeindexes(复合索引)
class Example1(db.Entity):
a = Required(str)
b = Optional(int)
composite_index(a, b)
#也可以使用字符串composite_index(a, 'b')

属性数据类型

格式为 :

属性名 = 属性类型(数据类型)

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
attr1 = Required(str)
# 等价
attr2 = Required(unicode)
attr3 = Required(LongStr)
# 等价
attr4 = Required(LongUnicode)
attr1 = Required(buffer) # Python 2 and 3
attr2 = Required(bytes) # Python 3 only
#字符串长度,不写默认为255
name = Required(str,40) #VARCHAR(40)
#整数的大小,默认2bit
attr1 = Required(int, size=8) # 8 bit - TINYINT in MySQL
attr2 = Required(int, size=16) # 16 bit - SMALLINT in MySQL
attr3 = Required(int, size=24) # 24 bit - MEDIUMINT in MySQL
attr4 = Required(int, size=32) # 32 bit - INTEGER in MySQL
attr5 = Required(int, size=64) # 64 bit - BIGINT in MySQL
#无符号整型
attr1 = Required(int, size=8, unsigned=True) # TINYINT UNSIGNED in MySQL
# 小数和精度
price = Required(Decimal, 10, 2) #DECIMAL(10,2)
# 时间
dt = Required(datetime,6)
# 其它参数
unique 是否唯一
auto 是否自增
default 默认值
sql_default
created_at = Required(datetime, sql_default='CURRENT_TIMESTAMP')
index 创建索引
index='index_name' 指定索引名称
lazy 延迟加载的属性加载对象
cascade_delete 关联删除对象
column 映射到数据库的列名
columns Set(多对多列名)
table 多对多中间表的表名字
nullable 允许该列为空
py_check 可以指定一个函数,检查数据是否合法和修改数据
class Student(db.Entity):
name = Required(str)
gpa = Required(float, py_check=lambda val: val >= 0 and val <= 5)

实例操作

# 获取实例
p = Person.get(name="Person") #返回单个实例,如同
Django ORM的get
#------------------------------
# 查询
persons = Person.select()
'''
select并没有连接数据库查询,只是返回一个Query object,调用persons[:]返回所有Person实例
'''
# limit
persons [1:5]
# show
persons.show()
# 生成器表达式查询,然后解析AST树的方式构造SQL语句
select(p for p in Person)
#和Person.select()一样返回Query object
select((p.id, p.name) for p in Person)[:]
# 带where条件查询
select((p.id, p.name) for p in Person if p.age ==20)[:]
# 分组聚合查询
select((max(p.age)) for p in Person)[:] #[25]
max(p.age for p in Person) #25
select(p.age for p in Person).max() #25
#-----------------------------
# 修改实例
@db_session
def update_persons():
p = Person.get(id=2)
p.page = 1000
commit()

# 删除
@db_session
def delete_persons():
p = Person.get(id=2)
p.delete()
commit()

pony使用还可以使用游标操作(这样就可以写原生sql语句了)

result = db.execute('''select name from Artist''')
print result.fetchall()

类似Django ORM的save函数

before_insert()
Is called only for newly created objects before it is inserted into the database.
before_update()
Is called for entity instances before updating the instance in the database.
before_delete()
Is called before deletion the entity instance in the database.
after_insert()
Is called after the row is inserted into the database.
after_update()
Is called after the instance updated in the database.
after_delete()
Is called after the entity instance is deleted in the database.

例如:

class Message(db.Entity):
title = Required(str)
content = Required(str)
def before_insert(self):
print("Before insert! title=%s" % self.title)

 


您可能感兴趣的文章:Python中编写ORM框架的入门指引研究Python的ORM框架中的SQLAlchemy库的映射关系Python的ORM框架中SQLAlchemy库的查询操作的教程利用Python的Django框架中的ORM建立查询API在Python的Django框架上部署ORM库的教程Python ORM框架SQLAlchemy学习笔记之数据查询实例Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍Python ORM框架SQLAlchemy学习笔记之关系映射实例Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例Python的ORM框架SQLAlchemy入门教程Python的ORM框架SQLObject入门实例

本文开发(python)相关术语:python基础教程 python多线程 web开发工程师 软件开发工程师 软件开发流程

主题: SQLMySQLDjango数据Python数据结构TI数据库AUTAU
tags: Required,db,name,pny,Artist,ORM,True,artist,Entity,Album,Python,database
分页:12
转载请注明
本文标题:详解python的ORM中Pony用法
本站链接:http://www.codesec.net/view/572629.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 开发(python) | 评论(0) | 阅读(60)