EXAMPLE FOR PEEWEE 多姿势使用 PEEWEE
使用 PEEWEE 断断续续的差不多已经三个年头了,但是没有像这次使用这么多的特性和功能,所以这次一并记录一下,需要注意的地方和一些使用细节,之后使用起来可能会更方便。
因为是使用的 SQLAchedemy 的引擎,所以增删改查的语法也很像。
查找方法
cls 这里默认指类对象了
查找单个会使用:
cls.get_one(cls.user_id == user_id)
查找批量可以使用:
cls.select().where(cls.user_id == user_id)
批量查找会返回一个数组,可以使用 for in 语句迭代他们。另外需要注意的一点是,如果需要指定查询的内容可以使用:
cls.select(cls.user_id, cls.id).where(cls.user_id == user_id)
里面也可以使用一些聚合函数例如 count sum 之类的
cls.select(cls.user_id, fn.COUNT(cls.id).alias('hahah')).where(xxxxx)
添加数据方法
User.create(username='Charlie')
类似使用这种语法,我们可以构造一个key: value 的字典,最后使用
User.create(**data)
一并写入即可。
注意,使用这种方法的返回值是有几条结果受到了影响。如果我们像知道添加了之后的主键 id 可以使用:
User.insert(username='Mickey').execute()
这种插入方法会返回 主键值。一般我们可以认为是 id 值。
批量插入方法
批量插入提供了很多种方法:
data_source = [
{'field1': 'val1-1', 'field2': 'val1-2'},
{'field1': 'val2-1', 'field2': 'val2-2'},
# ...
] for data_dict in data_source:
MyModel.create(**data_dict)
写到一个数组中,然后遍历一个一个插。。。亲测这是最慢的,如果另外几种行得通最好不要用。
with db.atomic():
for data_dict in data_source:
MyModel.create(**data_dict)
修改刚才那种方法的提交模式,让他们在同一个事务里面提交以此来提高速度。这次我的场景其实对插入速度要求很高,尝试了这种方法,但是我每次插入500条虽然速度是提高了不少,但是当我写到2000条的时候就报了一个事务的错误,在网上搜了一下也无果。所以对于量很大的插入,感觉这个方法也不是很好。。。或者欢迎来人指出的我使用姿势的问题。
另外的姿势:
# Fastest.
MyModel.insert_many(data_source).execute() # Fastest using tuples and specifying the fields being inserted.
fields = [MyModel.field1, MyModel.field2]
data = [('val1-1', 'val1-2'),
('val2-1', 'val2-2'),
('val3-1', 'val3-2')]
MyModel.insert_many(data, fields=fields).execute() # You can, of course, wrap this in a transaction as well:
with db.atomic():
MyModel.insert_many(data, fields=fields).execute()
第一种方法就是一个 list 然后里面是字典,只要你能保证这个结构,就可以进行批量插入。亲测速度不错,也没有遇到事务报错的问题。这次使用的就是这个方法,下面第二种第三种写法,感觉构造起来不是很友好。所以没有使用,有兴趣的朋友可以尝试。
修改数据方法
修改数据方法提供了普通的更新和原子更新方法。
普通的更新:
>>> today = datetime.today()
>>> query = Tweet.update(is_published=True).where(Tweet.creation_date < today)
>>> query.execute() # Returns the number of rows that were updated.
4
原子更新:
>>> query = Stat.update(counter=Stat.counter + 1).where(Stat.url == request.url)
>>> query.execute()
>>> subquery = Tweet.select(fn.COUNT(Tweet.id)).where(Tweet.user == User.id)
>>> update = User.update(num_tweets=subquery)
>>> update.execute()
还有一种 upsert 操作。如果指定键存在就执行更新操作,如果不存在执行插入操作。
下面提供了两种写法。
# Insert or update the user. The "last_login" value will be updated
# regardless of whether the user existed previously.
user_id = (User
.replace(username='the-user', last_login=datetime.now())
.execute()) # This query is equivalent:
user_id = (User
.insert(username='the-user', last_login=datetime.now())
.on_conflict_replace()
.execute())
另外 mysql 还提供了一种独有的语法 ON DUPLICATE KEY UPDATE 可以使用以下方法实现。
class User(Model):
username = TextField(unique=True)
last_login = DateTimeField(null=True)
login_count = IntegerField() # Insert a new user.
User.create(username='huey', login_count=0) # Simulate the user logging in. The login count and timestamp will be
# either created or updated correctly.
now = datetime.now()
rowid = (User
.insert(username='huey', last_login=now, login_count=1)
.on_conflict(
preserve=[User.last_login], # Use the value we would have inserted.
update={User.login_count: User.login_count + 1})
.execute())
上面的例子要注意 username 申明的 unique=true 如果模型上不申明可能会报错。
删除方法
删除方法跟普通的 orm 似乎设计得很像。要么获得一个 instance 然后调用 delete() 方法进行删除,要么就是直接条件查询直接删除,来看例子。
>>> user = User.get(User.id == 1)
>>> user.delete_instance() # Returns the number of rows deleted.
批量删除
>>> query = Tweet.delete().where(Tweet.creation_date < one_year_ago)
>>> query.execute() # Returns the number of rows deleted.
7
联表查询方法
query = (Tag
.select()
.join(PhotoTag)
.join(Photo)
.group_by(Tag)
.having(fn.Count(Photo.id) > 5))
其实 peewee 提供的方法就非常独立和干净。你可以按照自己的需求构造足够复杂的 sql ,语句也比较清晰。需要注意的是这几点,在联表查询的时候,select()函数里面需要写上自己需要的返回值,否则联表之后会发现竟然还是只有自己 cls 的字段,就会感觉到很疑惑。
query = User\
.select(User, UserDatum, Card7daysRecv)\
.join(UserDatum, JOIN.LEFT_OUTER, on=(User.uid == UserDatum.user_id))\
.join(Card7daysRecv, JOIN.LEFT_OUTER, on=(User.uid == Card7daysRecv.receive_uid)).order_by(User.create_time).limit(limit).offset(offset)
另外一些使用的时候需要注意的问题
在遇到复杂查询的时候有个不可缺少的工具就是打印以下自己的 orm 究竟构造了什么语句。可以使用 query.sql() 方便的看到。
谈下在 model 构造上的时候遇到的一些问题。
如果要往模型里面插数据,建议最好还是指定好 主键和默认值,以免读取模型的时候报错。需要的字段一定要在模型里面写上,否则拿的时候会发现没有这个字段。
class HdNewUserInfo(AliyunModel):
class Meta:
db_table = 'hd_new_user_info'
_version = 0 user_id = CharField(64, default='', primary_key=True)
phone = CharField(32, default='')
phone_province = CharField(64, default='')
phone_city = CharField(64, default='')
phone_community_id = CharField(32, default='')
name = CharField(64, default='')
head_img = CharField(1024, default='')
student_no = CharField(36, default='')
这里面其实还有个问题,我们在 mysql 5.6 5.7 还是会经常使用 timestamp 字段,并且使用它的默认当前时间字段。这在 peewee 里面的映射好像有点问题,如果我们使用 peewee 里面的 TimestampField 申明我们的字段,在读区和操作比较的时候可能会出现一些问题,会被调试需要的是 float 字段。但是 如果你使用 time.time() 类似的 float 去比较也会报出别的错误。但是使用 DateTimeField 却没有这个问题,所以我选择使用了 DateTimeField。
另外还有一个 database gone away 的问题。注意构造好自己的 db
class Off(Model):
class Meta:
database = db.offline_db_08_yanzhi @classmethod
def get_one(cls, *query, **kwargs):
try:
return cls.get(*query, **kwargs)
except DoesNotExist:
return None
初始化自己的 db。并且构造一个可以重连的 retrydb
class RetryOperationalError(object): def execute_sql(self, sql, params=None, commit=True):
try:
cursor = super(RetryOperationalError, self).execute_sql(
sql, params, commit)
except OperationalError:
if not self.is_closed():
self.close()
with __exception_wrapper__:
cursor = self.cursor()
cursor.execute(sql, params or ())
if commit and not self.in_transaction():
self.commit()
return cursor class MyRetryDB(RetryOperationalError, MySQLDatabase):
pass
这次玩数据暂时就遇到这些问题,以后再来补充。
Reference:
https://github.com/coleifer/peewee/issues/114 Print SQL queries
http://docs.peewee-orm.com/en/latest/peewee/query_examples.html#retrieve-the-start-times-of-members-bookings 联表查 example
https://stackoverflow.com/questions/15559468/why-is-peewee-including-the-id-column-into-the-mysql-select-query column into id 1 报错解决
EXAMPLE FOR PEEWEE 多姿势使用 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 ...
- tornado+peewee-async+peewee+mysql(一)
前言: 需要异步操作MySQL,又要用orm,使用sqlalchemy需要加celery,觉得比较麻烦,选择了peewee-async 开发环境 python3.6.8+peewee-async0.5 ...
- peewee的简单使用
peewee的简单使用 peewee是一个轻量级的ORM框架,peewee完全可以应对个人或企业的中小型项目的Model层,上手容易,功能强大. 一.安装peewee模块 使用pip命令工具安装pee ...
- 'ModelOptions' object has no attribute 'get_field_names
peewee安装时随意了点.装了2.8.0的. 倒回到2.6.0就好了. sudo pip uninstall peewee sudo pip install peewee==2.6.0
- [Python]Flask构建网站分析应用
原文Saturday morning hacks: Building an Analytics App with Flask - 由orangleliu友情翻译 ,主要是通过埋点技术来实现web网页的 ...
- Python 操作 MySQL 的5种方式(转)
Python 操作 MySQL 的5种方式 不管你是做数据分析,还是网络爬虫,Web 开发.亦或是机器学习,你都离不开要和数据库打交道,而 MySQL 又是最流行的一种数据库,这篇文章介绍 Pytho ...
- Python 程序员都会喜欢的 6 个库
在编程时,小挫折可能与大难题一样令人痛苦.没人希望在费劲心思之后,只是做到弹出消息窗口或是快速写入数据库.因此,程序员都会喜欢那些能够快速处理这些问题,同时长远来看也很健壮的解决方案. 下面这6个Py ...
- python&mysql
第一种方法,使用 pymysql库 import pymysql.cursors # Connect to the database connection = pymysql.connect(host ...
- Python 操作 MySQL 的5种方式
不管你是做数据分析,还是网络爬虫,Web 开发.亦或是机器学习,你都离不开要和数据库打交道,而 MySQL 又是最流行的一种数据库,这篇文章介绍 Python 操作 MySQL 的5种方式,你可以在实 ...
随机推荐
- Tomcat配置(部分知识点)
1.<Server>元素,shutdown属性表示关闭Server的指令:port属性表示Server接收shutdown指令的端口号,设为-1可以禁掉该端口 2.Connector的主要 ...
- 理解 tf.Variable、tf.get_variable以及范围命名方法tf.variable_scope、tf.name_scope
tensorflow提供了通过变量名称来创建或者获取一个变量的机制.通过这个机制,在不同的函数中可以直接通过变量的名字来使用变量,而不需要将变量通过参数的形式到处传递. 1. tf.Variable( ...
- Python:Day04
数学运算符: + 加 - 减 * 乘 ** 指数运算 / 除 // 整除 % 取余 比较运算符: > 大于 < 小于 >= 大于等于 <= 小于等于 == ...
- ubantu 安装 wget
sudo apt-get update sudo apt-get install wget wget
- ESP8266 HTTP 项目(1)在刻度盘上进行ESP8266 NodeMCU模拟读取的步骤
https://circuits4you.com/2018/02/03/esp8266-nodemcu-adc-analog-value-on-dial-gauge/ ESP8266(NodeMCU) ...
- ActiveMQ后台使用
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/nangeali/article/details/81514517默认地址 http://192.16 ...
- ElasticSearch(站内搜索) 转发 https://www.cnblogs.com/xibei666/p/5929970.html
简介 Elasticsearch是一个实时的分布式搜索和分析引擎.它可以帮助你用前所未有的速度去处理大规模数据.它可以用于全文搜索,结构化搜索以及分析,当然你也可以将这三者进行组合.Elasticse ...
- 【php增删改查实例】第二十六节 - 个人详情页制作
在一般的系统中,当用户点击头像的时候,就会跳转到对应的个人详情页,在这个页面,他可以查看和修改自己的个人信息,或者更换头像. 本案例中,个人详情页使用bootstrap框架. 首先,我们新建一个htm ...
- 单点登录SSO:概述与示例
目录 概述 演示一:零改造实施单点登录 演示二: 单点注销 演示三:集成AD认证 演示四:客户端单点登录 演示五:移动端单点登录 单点登录SSO概述 本系列将由浅入深的,带大家掌握最新单点登录SSO方 ...
- .net core实践系列之短信服务-目录
前言 经过两周多的业余时间,终于把该系列的文章写完了.第一次写系列,可能部分关键点并没有覆盖到,如果有疑问的朋友可以随时反馈给我.另外也感谢在我发布文章时给予我方案建议与反馈源码BUG的朋友们.下面是 ...