PEEWEE基本使用

Content 
Ⅰ  安装
Ⅱ  链接数据库
Ⅲ  建表
Ⅳ  增删改
Ⅴ  基础查询
Ⅵ  ForeignKey
Ⅷ  事务

参考官方文档:http://docs.peewee-orm.com/en/latest/index.html

1. 安装

pip install peewee

2. 链接数据库

以mysql 为例(Peewee提供mysql,postgresql,sqllite)的支持

import peewee
settings = {'host': 'localhost', 'password': '', 'port': 3306, 'user': 'root'}
db = peewee.MySQLDatabase("test",**settings)

3. 建表

3.1 表关系

class Person(Model):
name = CharField(verbose_name='姓名', max_length=10, null=False, index=True)
passwd = CharField(verbose_name='密码', max_length=20, null=False, default='')
email = CharField(verbose_name='邮件', max_length=50, null=True, unique=True)
gender = IntegerField(verbose_name='姓别', null=False, default=1)
birthday = DateField(verbose_name='生日', null=True, default=None)
is_admin = BooleanField(verbose_name='是否是管理员', default=True)
class Meta:
database = db # 这里是数据库链接,为了方便建立多个表,可以把这个部分提炼出来形成一个新的类
     table_name = 'persons' # 这里可以自定义表名

# 例如:
    class BaseModel(Model):
   class Meta:
   database = db
class Person(BaseModel):
   name = CharField()
全部数据类型
Field Type Sqlite Postgresql MySQL
IntegerField integer integer integer
BigIntegerField integer bigint bigint
SmallIntegerField integer smallint smallint
AutoField integer serial integer
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 longtext
BlobField blob bytea blob
BitField integer bigint bigint
BigBitField blob bytea blob
UUIDField text uuid varchar(40)
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
null = False – 可否为空
index = False – index索引
unique = False – unique索引
column_name = None – string representing the underlying column to use if different, useful for legacy databases
default = None – 默认值,如果callable, 会调用生成!
primary_key = False – 主键
constraints = None - a list of one or more constraints, e.g. [Check('price > 0')]
sequence = None – sequence to populate field (if backend supports it)
collation = None – collation to use for ordering the field / index
unindexed = False – indicate field on virtual table should be unindexed (SQLite-only)
choices = None – an optional iterable containing 2-tuples of value, display
help_text = None – string representing any helpful text for this field
verbose_name = None – string representing the “user-friendly” name of this field

所有属性

3.2 链接数据库

db.is_closed()  # 判断数据库是不是链接
db.connect() # 数据库链接

3.3 建库

db.create_tables([Person,]) #建库

#   如果数据表已经存在,执行create_table的时候,将会抛出异常。

3.4 主键和约束

class Person(Model):
first = CharField()
last = CharField() class Meta:
primary_key = CompositeKey('first', 'last') class Pet(Model):
owner_first = CharField()
owner_last = CharField()
pet_name = CharField() class Meta:
constraints = [SQL('FOREIGN KEY(owner_first, owner_last) '
'REFERENCES person(first, last)')]

主键和约束

class BlogToTag(Model):
"""A simple "through" table for many-to-many relationship."""
blog = ForeignKeyField(Blog)
tag = ForeignKeyField(Tag) class Meta:
primary_key = CompositeKey('blog', 'tag')

复合主键

User._meta.auto_increment = False # turn off auto incrementing IDs

关自增

4. 插&改&删

4.1 插

p = Person.create(name='master')
####### 或 #########
p = Person(name="master")
p.save()
data = [
{'facid': 9, 'name': 'Spa', 'membercost': 20, 'guestcost': 30,
'initialoutlay': 100000, 'monthlymaintenance': 800},
{'facid': 10, 'name': 'Squash Court 2', 'membercost': 3.5,
'guestcost': 17.5, 'initialoutlay': 5000, 'monthlymaintenance': 80}]
query = Facility.insert_many(data) # 插入了多个
with db.atomic():  # 一次链接
for data_dict in data_source:
MyModel.create(**data_dict)
 
User.insert(username='Mickey').execute()  # >>> 返回主键
# insert_from 是指从一个表查数据快速差到另一个表
query = (TweetArchive
.insert_from(
Tweet.select(Tweet.user, Tweet.message),
fields=[Tweet.user, Tweet.message])
.execute())

insert_from

4.2 改

p.email = "qq@qq.com"  # p 为记录对象
p.save() # 会调用update 但是不要这么写!
query = (Facility
.update(membercost=6, guestcost=30)
.where(Facility.name.startswith('Tennis'))) 
query.execute()  # 元子操作

4.3 注意

插入的时候,如果字段设置了default值,则会按照default指定的值插入,如果没有指定,同时字段可以为null,则数据库自动初始化值为null,如果字段不能为null,则数据库自动初始化为其零值。 如果字段为非Null,最好设置default值,同时数据库schema也设置其default值,如果字段为可以为null,那么初始值就设置为null即可。

4.4 数据删除

p.delete_instance()
query = Member.delete().where(Member.memid == 37)

# DELETE FROM members WHERE NOT EXISTS (SELECT * FROM bookings WHERE bookings.memid = members.memid);
subq = Booking.select().where(Booking.member == Member.memid)
query = Member.delete().where(~fn.EXISTS(subq)) # 同样这样的操作是被推荐的

5. 基础查询

  基本和sql语句相同

User.get(User.id == 1)

User.get_by_id(1)  # Same as above.

User[1]  # Also same as above.
g = Person.select().where(Person.name == 'Grandma L.').get()   # where是查询一个集合, select是查询字段

g = Person.get(Person.name == 'fff.')   # get是得到第一个

g = Person.select().where(Person.age > 23).get()
# select 代表sql语句中select后面的语句表示要展示的字段 # where 代表where条件语句 得到一个数据集合,用for循环遍历 # get()代表找第一个

5.1 复合条件

query1 = Person.select().where((Person.name == "fff0") | (Person.name == "sss1"))

query2 = Person.select().where((Person.name == "fff") & (Person.is_relative == True))
==    x equals y
< x is less than y
<= x is less than or equal to y
> x is greater than y
>= x is greater than or equal to y
!= x is not equal to y
<< x IN y, where y is a list or query
>> x IS y, where y is None/NULL
% x LIKE y where y may contain wildcards
** x ILIKE y where y may contain wildcards
^ x XOR y
~ Unary negation (e.g., NOT x)

操作符

5.2 模糊查询

#SELECT * FROM person WHERE name ILIKE '%tennis%';

Person.select().where(Person.name ** "%fff%").get()
######### OR ##############
query = Facility.select().where(Facility.name.contains('tennis'))

5.3 In 查询

# SELECT * FROM facilities WHERE facid IN (1, 5);
query = Facility.select().where(Facility.facid.in_([1, 5]))
person, created = Person.get_or_create(
first_name=first_name,
last_name=last_name,
defaults={'dob': dob, 'favorite_color': 'green'}) # defaults dictionary, which will be used to populate values on newly-created instances.

get_or_create

query = User.select().dicts()
for row in query:
print(row)
# row 是什么字典

字典展示(还可以tuples(),namedtuples(),objects())

5.4 Order by; Limit; Distinct; Group by; Having

query = (Person.select(Person.name).order_by(Person.name).limit(10).distinct())  # 几乎和sql一模一样
Person.select().order_by(Person.birthday.desc())  # 日期排序
query = (Booking
.select(Booking.facid, fn.SUM(Booking.slots))
.group_by(Booking.facid) # group_by
.order_by(Booking.facid))
query = (Booking
.select(Booking.facility, fn.SUM(Booking.slots))
.group_by(Booking.facility)
.having(fn.SUM(Booking.slots) > 1000) # having
.order_by(Booking.facility))
 
Tweet.select().order_by(-Tweet.created_date) 
# Similarly you can use "+" to indicate ascending order, though ascending

5.5 聚合函数

# SELECT MAX(birthday) FROM person;
query = Person.select(fn.MAX(Person.birthday))
# SELECT name, is_relative FROM person WHERE birthday = (SELECT MAX(birthday) FROM person);
MemberAlias = Member.alias()  # 如果一个查询中用了两个表,需要这个Alias作为影子
subq = MemberAlias.select(fn.MAX(MemberAlias.joindate))
query = (Member.select(Person.is_relative, Person.name, ).where(Person.birthday == subq))

5.6 分页&计数

for tweet in Tweet.select().order_by(Tweet.id).paginate(2, 10):
print(tweet.message) # paginate两个参数:page_number 和 items_per_page

分页

# 返回查到了多少条记录
Tweet.select().where(Tweet.id > 50).count()

count

5.7 SQL

query = MyModel.raw('SELECT * FROM my_table WHERE data = %s', user_data)
query = MyModel.select().where(SQL('Some SQL expression %s' % user_data))
# sql 注入: ensure that any user-defined data is passed in as a query parameter and not part of the actual SQL query

原生sql

6. ForeignKey

6.1 表关系

class Pet(peewee.Model):
name = peewee.CharField()
owner = peewee.ForeignKeyField(Person,related_name="pets",backref="petties")
  # backref是反查的字段,如果有related_name用related_name反查,如果没有直接用petties反查 e.g. [i.name for i in Person.get(name="aaa").petties] class Meta: database = db
class Category(Model):
name = CharField()
parent = ForeignKeyField('self', null=True, backref='children')
# 注意自关联永远是null = True

自关联

6.2 插

g2 = Person.get(tablesinfo.Person.is_relative == False)
d2 = Pet.create(name="dog2",owner=g2)

6.3 正反查

#正查
dog1 = Pet.get(name="dog1")
dog1.owner.name # 反查
aaa = Person.get(name="aaa").pets # pets为related_name字段,如果没写用backref字段
for a in aaa:
print(i.name)

6.4 连表查询

g1 = Person.select().join(Pet).where(Pet.name == "dog2")

6.5 复杂连表

# SELECT DISTINCT m.firstname, m.surname FROM members AS m2
INNER JOIN members AS m ON (m.memid = m2.recommendedby)
ORDER BY m.surname, m.firstname; MA = Member.alias()
query = (Member
.select(Member.firstname, Member.surname)
.join(MA, on=(MA.recommendedby == Member.memid)) # join中用on表示链接方法
.order_by(Member.surname, Member.firstname))

6.6 连多表

User.select().join(Tweet).join(Comment)

Artist.select().join(Album).switch(Artist).join(Genre) # 如果连一表多次

连多表

6.7 多对多

class BaseModel(Model):
class Meta:
database = db class Student(BaseModel):
name = CharField() class Course(BaseModel):
name = CharField()
students = ManyToManyField(Student, backref='courses')
StudentCourse = Course.students.get_through_model()  # 中间表
huey = Student.get(Student.name == 'Huey')

# We can add all the objects represented by a query.
english_courses = Course.select().where(
Course.name.contains('english'))
huey.courses.add(english_courses)

add

huey = Student.get(Student.name == 'Huey')
for course in huey.courses.order_by(Course.name):
print(course.name)

huey.courses.remove(Course.select().where(Course.name.startswith('CS')))
engl_101.students.remove(huey)

remove

7 事务

with db.atomic() as transaction:  # Opens new transaction.
try:
save_some_objects()
except ErrorSavingData:
# Because this block of code is wrapped with "atomic", a
# new transaction will begin automatically after the call
# to rollback().
transaction.rollback()
error_saving = True

atomic和rollback

db = SqliteDatabase(':memory:')

with db.atomic() as txn:
# This is the outer-most level, so this block corresponds to
# a transaction.
User.create(username='charlie') with db.atomic() as nested_txn:
# This block corresponds to a savepoint.
User.create(username='huey') # This will roll back the above create() query.
nested_txn.rollback() User.create(username='mickey') # When the block ends, the transaction is committed (assuming no error
# occurs). At that point there will be two users, "charlie" and "mickey".

atomic甚至可以多层嵌套

@db.atomic()
def create_user(username):
# This statement will run in a transaction. If the caller is already
# running in an `atomic` block, then a savepoint will be used instead.
return User.create(username=username) create_user('charlie')

装饰器模式

# 纯手动用commit()提交,用rollback回滚
with db.transaction() as txn:
User.create(username='mickey')
txn.commit() # Changes are saved and a new transaction begins.
User.create(username='huey') # Roll back. "huey" will not be saved, but since "mickey" was already
# committed, that row will remain in the database.
txn.rollback() # 半自动用savepoint上下文管理
with db.transaction() as txn:
with db.savepoint() as sp:
User.create(username='mickey') with db.savepoint() as sp2:
User.create(username='zaizee')
sp2.rollback() # "zaizee" will not be saved, but "mickey" will be.

手动、半自动

8 其他

import uuid

class UUIDField(Field):
field_type = 'uuid' def db_value(self, value):
return str(value) # convert UUID to str def python_value(self, value):
return uuid.UUID(value) # convert str to UUID

自定义类型!

Person._meta.fields   # 用访问_meta访问定义的meta
Person._meta.primary_key
Person._meta.database # 属性有:database, table_name, table_function, indexes, primary_key, constraints, schema, only_save_dirty, options, table_alias, depends_on, without_rowid

数据表信息的访问

class Article(Model):
name = TextField()
timestamp = TimestampField()
status = IntegerField()
flags = IntegerField() # Add an index on "name" and "timestamp" columns.
Article.add_index(Article.name, Article.timestamp) # Add a partial index on name and timestamp where status = 1.
Article.add_index(Article.name, Article.timestamp,
where=(Article.status == 1)) # Create a unique index on timestamp desc, status & 4.
idx = Article.index(
Article.timestamp.desc(),
Article.flags.bin_and(4),
unique=True)
Article.add_index(idx)

索引增加

事务autocommit模式(不推荐)
Employee.select(fn.Min(Employee.salary), fn.Max(Employee.salary) ).scalar(as_tuple=True)
# You can retrieve multiple scalar values by passing as_tuple=True # scalar 表示结果的第一行第一列

scalar

注:原生sql,推荐 https://pypi.python.org/pypi/records/

peewee基本使用的更多相关文章

  1. Python’s SQLAlchemy vs Other ORMs[转发 4]peewee

    peewee peewee is a small, expressive ORM. Compared to other ORMs, peewee focuses on the principal of ...

  2. peewee Model.get的复杂查询

    (a | b )&c 官方文档没有具体讲到,又没有太多时间来看源码.经过尝试, (a | b) and c (a or b) and c 都是可以的. 而  (a | b) &c 是不 ...

  3. [Python]peewee使用经验

    peewee 使用经验 本文使用案例是基于 python2.7 实现 以下内容均为个人使用 peewee 的经验和遇到的坑,不会涉及过多的基本操作.所以,没有使用过 peewee,可以先阅读文档 正确 ...

  4. Python ORM框架之 Peewee入门

    之前在学Django时,发现它的模型层非常好用,把对数据库的操作映射成对类.对象的操作,避免了我们直接写在Web项目中SQL语句,当时想,如果这个模型层可以独立出来使用就好了,那我们平台操作数据库也可 ...

  5. Python:轻量级 ORM 框架 peewee 用法详解(二)——增删改查

    说明:peewee 中有很多方法是延时执行的,需要调用 execute() 方法使其执行.下文中不再特意说明这个问题,大家看代码. 本文中代码样例所使用的 Person 模型如下: class Per ...

  6. Python:用 peewee 框架连接 SQL Server

    Peewee 默认支持 Sqlite.MySQL.PostgreSQL 三种数据库,如果要使用其他数据库,需要同时安装扩展库.比如 SQL Server,需要安装 peewee-mssql. 但是安装 ...

  7. [Python]peewee 使用经验

    peewee 使用经验 本文使用案例是基于 python2.7 实现 以下内容均为个人使用 peewee 的经验和遇到的坑,不会涉及过多的基本操作.所以,没有使用过 peewee,可以先阅读文档 正确 ...

  8. peewee insert 数据时报错:'buffer' object has no attribute 'translate'

    错误信息: "'buffer' object has no attribute 'translate'" 场景:使用peewee insert 数据时,BlobField 字段存储 ...

  9. peewee 通俗易懂版

    Peewee作为Python ORM之一 优势:简单,小巧,易学习,使用直观 不足之处:需要手动创建数据库 基本使用流程 1⃣️根据需求定义好Model(表结构类) 2⃣️通过create_table ...

随机推荐

  1. 关于d3.js 将一个element 拖拽到另一个element的响应事件

    rt 正在做机柜可视化, 一个需求是能拖拽左侧列表的设备名称, 拖到右侧42U机柜中,并将设备图片放置在对应机柜位置上. 开始的时候一切都很顺利,点击左侧设备名称,添加一个g容器,将设备名称作为tex ...

  2. linux之egrep命令

    1.介绍 egrep工具是grep工具的扩展,相当于grep -E 2.用法 查找1个或1个以上前面的字符为例 查找0个或1个前面字符 egrep 'o?' 1.txt 匹配roo或者body egr ...

  3. 【python深入】map/reduce/lambda 内置函数的使用

    python中的内置函数里面,有map和reduce两个方法,这两个方法可以非常好的去做一些事情,但是之前都没有用过,下面是关于这两个方法的介绍: 一.map相关 map()会根据提供的函数对指定的序 ...

  4. 用python计算圆周率PI

    1.蒙特卡洛求圆周率 向区域内随即撒点 当点的数目足够多时,落在圆的点数目与在正方形点数目成正比 即圆的面积和正方形的面积成正比 可以得出计算圆周率的算法 DARTS=100000000   hits ...

  5. Python __dict__属性详解

    本文转载自 https://www.cnblogs.com/alvin2010/p/9102344.html 感谢 //偏执 大佬 我们都知道Python一切皆对象,那么Python究竟是怎么管理对象 ...

  6. 关于接口测试工具postman与DHC介绍

    一.Postman背景介绍 用户在开发或者调试网络程序或者是网页B/S模式的程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的Firebug等网页调试工具.今天给大家介 ...

  7. 201621123002《java程序设计》第九周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 //功能需求:将所有大于5的生成一个新的List对象 List lis ...

  8. 计数排序之python

    话说,一口气不能吃个胖子, 一次性 学习 计数排序, 也确实容易消化不良. 下面,我们逐步学习下计数排序. 1.  已知一个简单列表 l1 = [5, 4, 3], 分析下这个列表的情况 5 > ...

  9. 在Jenkins上配置批处理删除远程共享目录7天以上的文件

    net use * /del /yes NET USE X: \\10.29.48.12\shares\Test password /user:DOMAIN1\account set AutoPath ...

  10. springmvd接收参数问题

    问题描述: 好久不写博客了,今天遇到一个问题,那就是post请求时,参数接收不到,当时我很纳闷,看代码: 就是这样几个参数,我使用postman请求时无法获取参数: 报错信息: "msg&q ...