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)
索引增加
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基本使用的更多相关文章
-
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 ...
-
peewee Model.get的复杂查询
(a | b )&c 官方文档没有具体讲到,又没有太多时间来看源码.经过尝试, (a | b) and c (a or b) and c 都是可以的. 而 (a | b) &c 是不 ...
-
[Python]peewee使用经验
peewee 使用经验 本文使用案例是基于 python2.7 实现 以下内容均为个人使用 peewee 的经验和遇到的坑,不会涉及过多的基本操作.所以,没有使用过 peewee,可以先阅读文档 正确 ...
-
Python ORM框架之 Peewee入门
之前在学Django时,发现它的模型层非常好用,把对数据库的操作映射成对类.对象的操作,避免了我们直接写在Web项目中SQL语句,当时想,如果这个模型层可以独立出来使用就好了,那我们平台操作数据库也可 ...
-
Python:轻量级 ORM 框架 peewee 用法详解(二)——增删改查
说明:peewee 中有很多方法是延时执行的,需要调用 execute() 方法使其执行.下文中不再特意说明这个问题,大家看代码. 本文中代码样例所使用的 Person 模型如下: class Per ...
-
Python:用 peewee 框架连接 SQL Server
Peewee 默认支持 Sqlite.MySQL.PostgreSQL 三种数据库,如果要使用其他数据库,需要同时安装扩展库.比如 SQL Server,需要安装 peewee-mssql. 但是安装 ...
-
[Python]peewee 使用经验
peewee 使用经验 本文使用案例是基于 python2.7 实现 以下内容均为个人使用 peewee 的经验和遇到的坑,不会涉及过多的基本操作.所以,没有使用过 peewee,可以先阅读文档 正确 ...
-
peewee insert 数据时报错:&#39;buffer&#39; object has no attribute &#39;translate&#39;
错误信息: "'buffer' object has no attribute 'translate'" 场景:使用peewee insert 数据时,BlobField 字段存储 ...
-
peewee 通俗易懂版
Peewee作为Python ORM之一 优势:简单,小巧,易学习,使用直观 不足之处:需要手动创建数据库 基本使用流程 1⃣️根据需求定义好Model(表结构类) 2⃣️通过create_table ...
随机推荐
-
Consul 服务发现和配置
Service discovery and configuration made easy. Distributed, highly available, and datacenter-aware. ...
-
Elasticsearch在Windows下的安装
下载Elasticsearch,地址:elasticsearch.org/download 下载jdk,百度搜索jdk下载即可 配置JAVA_HOME变量,配置方法在此文:http://jingyan ...
-
NBUT1457 Sona 莫队算法
由于10^9很大,所以先离散化一下,把给你的这一段数哈希 时间复杂度O(nlogn) 然后就是分块莫队 已知[L,R],由于事先的离散化,可以在O(1)的的时间更新[l+1,r],[l,r+1],[l ...
-
.Net平台-MVP模式再探(二)
PS: 本文与 上一遍文章 没有什么必然的联系,可以说是对于MVP的一定的加深,或许在理解上比上一篇多有点难度. 正文 一.简单讲讲MVP是什么玩意儿 如果从层次关系来讲,MVP属于P ...
-
hdu_2255_奔小康赚大钱(KM带权二分匹配板子)
题目连接:hdu_2255_奔小康赚大钱 存个板子 /* 其实在求最大 最小的时候只要用一个模板就行了, 把边的权值去相反数即可得到另外一个.求结果的时候再去 相反数即可,最大最小有一些地方不同.. ...
-
JVM中的垃圾回收器及垃圾收集算法描述
首先需要了解下JVM(Java虚拟机)中的内存分配情况: 收集器的介绍: Serial收集器:是最原始的收集器,是单线程的,实现简单,但是在后台收集垃圾的时候,其他的工作线程都会停止,直到垃圾收集线程 ...
-
java的优点和误解 《java核心技术卷i》第一章
<java核心技术卷i>第一章主要内容包括三点: 1:Java白皮书的关键术语:描述Java的十一个关键字: 2:Java applet 3 :关于Java的常见误解 1:第一章:Ja ...
-
蛋白质结构模型和功能预测:I-TASSER工具的使用
I-TASSER是一款用于预测蛋白质结构和功能的工具,网站链接:https://zhanglab.ccmb.med.umich.edu/I-TASSER/ 具体描述如下: I-TASSER (Iter ...
-
wfst的compose算法
介绍一些compose算法,以及这部分的代码实现. 原理部分参考: 走进语音识别中的 WFST(二) 可以看下示例图: 我们先来看一下 Composition 的效果,图(a)和图(b)Composi ...
-
.net部署时常见问题
站点提示“不允许的父路径”怎么办 error: 40 - Could not open a connection to SQL Server解决办法 无法识别的属性“targetFramework”. ...