ORM与peewee
一、为什么要用ORM
- 隔离数据库和数据库版本之间的差异
- 便于维护
- ORM会提供防sql注入等功能
- 变量传递式的调用更加简单
- ORM越来越流行
二、ORM的选择
框架 | 优点 | 缺点 |
---|---|---|
peewee | Django式的API,使其易用 轻量实现,很容易和任意web框架集成 | 不支持自动化 schema 迁移 多对多查询写起来不直观 |
SQLObject | 采用了易懂的ActiveRecord 模式 ;一个相对较小的代码库 | 方法和类的命名遵循了Java 的小驼峰风格 ;不支持数据库session隔离工作单元 |
Storm | 清爽轻量的API,短学习曲线和长期可维护性;不需要特殊的类构造函数,也没有必要的基类 | 迫使程序员手工写表格创建的DDL语句,而不是从模型类自动派生;Storm的贡献者必须把他们的贡献的版权给Canonical公司 |
Django’s ORM | 易用,学习曲线短;和Django紧密集合,用Django时使用约定俗成的方法去操作数据库 | 不好处理复杂的查询,强制开发者回到原生SQL;紧密和Django集成,使得在Django环境外很难使用 |
SQLAlchemy | 企业级 API,使得代码有健壮性和适应性;灵活的设计,使得能轻松写复杂查询 | 工作单元概念不常见;重量级 API,导致长学习曲线 |
我们选择peewee
这个框架来学习,因为它简单、灵活、申明方式和django的ORM接近。且star数量高,活跃度高,文档质量高。
官方文档:http://docs.peewee-orm.com/en/latest/
三、peewee使用
1. 安装
切换到虚拟环境,然后安装
pip install peewee
2. 创建并使用
from peewee import *
db = MySQLDatabase("py_spider", host="localhost", port=3307, user="root", password="root")
class Person(Model):
name = CharField()
birthday = DateField()
class Meta:
database = db # This model uses the "people.db" database.
if __name__ == "__main__":
db.create_tables([Person]) # 根据模型创建数据表
生成的数据表,表名默认为类名,默认会加一个ID字段(主键):
Field types table(数据库与模型字段对应表)
Field Type | Sqlite | Postgresql | MySQL |
---|---|---|---|
AutoField | integer | serial | integer |
BigAutoField | integer | bigserial | bigint |
IntegerField | integer | integer | integer |
BigIntegerField | integer | bigint | bigint |
SmallIntegerField | integer | smallint | smallint |
IdentityField | not supported | int identity | not supported |
FloatField | real | real | real |
DoubleField | real | double precision | double precision |
DecimalField | decimal | numeric | numeric |
CharField | varchar | varchar | varchar |
FixedCharField | char | char | char |
TextField | text | text | text |
BlobField | blob | bytea | blob |
BitField | integer | bigint | bigint |
BigBitField | blob | bytea | blob |
UUIDField | text | uuid | varchar(40) |
BinaryUUIDField | blob | bytea | varbinary(16) |
DateTimeField | datetime | timestamp | datetime |
DateField | date | date | date |
TimeField | time | time | time |
TimestampField | integer | integer | integer |
IPField | integer | bigint | bigint |
BooleanField | integer | boolean | bool |
BareField | untyped | not supported | not supported |
ForeignKeyField | integer | integer | integer |
3. 增删查改
(1) 新增
if __name__ == "__main__":
# db.create_tables([Person]) # 创建数据表
from datetime import date
# 生成数据
bob = Person(name="Bob", birthday=date(2020, 12, 12))
# 新增数据到数据库
bob.save()
(2) 查询数据
if __name__ == "__main__":
# 只查询一条数据 get方法在取不到数据会抛出异常,需try catch
Bob = Person.select().where(Person.name == 'Bob').get()
print(Bob.name) # Bob
print(Bob.birthday) # 2020-12-12
# 同上
Bob2 = Person.get(Person.name == 'Bob')
print(Bob2.name) # Bob
print(Bob2.birthday) # 2020-12-12
# 查询多条数据
Bobs = Person.select().where(Person.name == 'Bob')
for b in Bobs:
print(b.name)
print(b.birthday)
(3) 修改数据
if __name__ == "__main__":
from datetime import date
# 修改数据
Bobs = Person.select().where(Person.name == 'Bob')
for b in Bobs:
b.birthday = date(1997, 10, 16)
b.save() # 在没有数据的时候新增,存在的时候修改
(4) 删除数据
if __name__ == "__main__":
# 删除数据
Bobs = Person.select().where(Person.name == 'Bob')
for b in Bobs:
b.delete_instance()