本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes

1 简介

   这是我的系列教程Python+Dash快速web应用开发的第十七期,在之前的各期教程中,我们针对Dash中各种基础且常用的概念展开了学习,但一直没有针对与数据库之间交互进行专门的介绍,只是在某些示例中利用pandasSQLAlchemy等工具简陋地操作数据库。

  而在今天的教程中,我就将带大家学习在Dash中利用简单好用的ORMpeewee,快速高效地将数据库整合进Dash应用中。

图1

2 利用peewee在Dash中整合数据库

  说起peewee,很多使用过ORM(Object Relational Mapping,对象关系映射)工具的朋友都听说过,它跟SQLAlchemy等框架从功能上看都大同小异,目的都是为了不写SQL,而是利用面向对象编程的方式,在Python中实现常用的SQL功能。

图2

  peewee虽然相比SQLAlchemy等重型的ORM框架已经轻量很多了,但内容还是非常丰富,我们今天就针对一些典型场景,展示一下其与Dash应用如何相互结合。

2.1 创建数据表

  利用peewee构建数据表,需要定义相应的Model类,在类中构建的属性即对应表中的字段,并且在Meta类中定义其他的一些属性,譬如下面的例子我们就以最简单的SQLite数据库为例:

model1.py

from peewee import SqliteDatabase, Model
from peewee import CharField, IntegerField, DateTimeField from datetime import datetime # 关联数据库,对于sqlite数据库若不存在则会直接创建
db = SqliteDatabase('17 整合数据库/model1.db') class Model1(Model): # 用户名为字符型,并设置唯一性约束
username = CharField(unique=True) # 用户等级设定为整数型
level = IntegerField() # 用户加入时间为时间日期类型
join_datetime = DateTimeField() class Meta:
database = db # 指定数据库
table_name = 'user_info' # 自定义数据表名,不设置则自动根据类名推导 # 创建数据表,若对应数据库中已存在此表,则会跳过
db.create_tables([Model1])

  上述的代码在执行之后,便会在关联到的SQLite数据库中创建对应的表:

图3

  而除了最简单的SQLite之外,peewee还支持MySQLPostgreSQL,你可以在http://docs.peewee-orm.com/en/latest/peewee/database.html查看更多使用示例,关于更多有关Model创建的知识可以参考http://docs.peewee-orm.com/en/latest/peewee/models.html

2.2 向表中新增记录

  在数据表创建完成之后,我们第一件事当然是要向表中插入数据,这在peewee中操作非常简单:

  • 插入单条数据

  在peewee中向表中插入单条记录可以使用create()方法:

# 创建单条记录
Model1.create(username='张三', level=6, join_datetime=datetime(2020, 1, 1, 10, 28, 45)) Model1.create(username='李四', level=1, join_datetime=datetime(2020, 5, 1, 10, 28, 45))

  执行完上述命令后旋即会更新到数据库表中:

图4

  • 插入多条数据

  在peewee中批量插入数据可以使用insert_many()方法传入对应每行内容的字典列表,记得最后要跟着执行execute()方法才会真正向数据库执行:

# 批量插入数据
(
Model1
.insert_many([
{'username': '王五', 'level': 3, 'join_datetime': datetime(2020, 3, 1, 10, 28, 45)},
{'username': '赵六', 'level': 2, 'join_datetime': datetime(2020, 4, 1, 10, 28, 45)}])
.execute()
)

图5

2.3 从表中删除数据

  对于已存在数据的表,进行数据删除可以使用到delete()方法其后再链式上where()来声明判断条件,最后同样跟上execute()方法执行即可,如果要清空整张表则不用加where(),譬如我们要删除level小于3的记录:

# 删除level小于3的记录
Model1.delete().where(Model1.level < 3).execute()

图6

  更多关于peewee数据删除的知识可以参考官方文档http://docs.peewee-orm.com/en/latest/peewee/querying.html#deleting-records部分内容。

2.4 对表中数据进行更新

  作为增删改查中非常重要的,在peewee中实现也是非常的方便,基础的用法是配合update()where()如下面的例子那样:

# 修改username为张三的记录值level字段为8
Model1.update(level=8).where(Model1.username == '张三').execute()

图7

  更多内容可参考官方文档http://docs.peewee-orm.com/en/latest/peewee/querying.html#updating-existing-records

2.5 对表中数据进行查询

  作为增删改查中使用频次最高的,在peewee中涉及到的知识内容非常之庞大,但基础的格式都是利用select()方法,常用的有以下方式:

# 获取查询结果方式1:
query_results = Model1.select().where(Model1.level > 2).execute() for query_result in query_results:
print(query_result.username)

图8

# 获取查询结果方式2:
query_results = Model1.select().where(Model1.level > 2).dicts()
list(query_results)

图9

  而有关跨表连接等进阶的查询操作,请参考官方文档http://docs.peewee-orm.com/en/latest/peewee/query_examples.html#query-examples

2.6 基于已存在的表逆向生成Model

  如果你的数据库表已然存在,又希望生成相应的Model类,peewee提供了命令行工具帮我们做这件事,以SQLite为例:

python -m pwiz -e sqlite model1.db >model2.py

  自动生成的model2.py代码如下,在这个基础上我们可以进一步的优化修改:

from peewee import *

database = SqliteDatabase('model1.db')

class UnknownField(object):
def __init__(self, *_, **__): pass class BaseModel(Model):
class Meta:
database = database class UserInfo(BaseModel):
join_datetime = DateTimeField()
level = IntegerField()
username = CharField(unique=True) class Meta:
table_name = 'user_info'

  而更多关于peewee利用pwiz生成Model类的参数和用法可参考官方文档http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#pwiz-a-model-generator

3 peewee配合Dash实现在线留言板功能

  getpeewee的常用基础用法之后,我们回到本文的重点——结合Dash整合数据库,要实现的功能很简单,就是实现一个在线留言板,每个访问应用的用户都可以在填写若干信息后,发表自己的留言,其他用户后续访问可以看到前面用户发表过的留言信息。

  为了方便演示,我选择SQLite作为示例数据库,首先我们需要构建一个model.py来设计表模型,来存放每条留言信息,并自定义一些功能函数:

model.py

from peewee import SqliteDatabase, Model
from peewee import CharField, DateTimeField, TextField
from datetime import datetime db = SqliteDatabase('17 整合数据库/message_board.db') class MessageBoard(Model):
nickname = CharField() pub_date = DateTimeField() message_content = TextField() class Meta:
database = db # 指定数据库
table_name = 'message_board' # 自定义数据表名,不设置则自动根据类名推导 db.create_tables([MessageBoard]) # 新增留言记录
def submit_new_message(nickname, message_content):
MessageBoard.create(
nickname=nickname,
pub_date=datetime.now(),
message_content=message_content
) # 获取全部留言记录
def fetch_all_message():
return list(MessageBoard.select().dicts())

  接着我们只需要在对应Dash应用的app.py中调用model.py中的相关功能即可,效果如下(动图录制有些花屏,大家可以自己运行尝试,效果更佳):

图10

app.py

import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State from model import MessageBoard, submit_new_message, fetch_all_message app = dash.Dash(__name__) app.layout = html.Div(
dbc.Container(
[
html.Div(style={'height': '20px'}),
html.H2('Dash示例留言板'),
dbc.Container(
id='history-message',
style={
'paddingTop': '50px',
'width': '70%',
'height': '70%',
'overflowY': 'auto',
'backgroundColor': '#fafafa'
}
),
dbc.Container(
dbc.Row(
[
dbc.Col(
dbc.Input(placeholder='输入昵称:', id='nickname', style={'width': '100%'}),
width=3,
style={
'padding': 0
}
),
dbc.Col(
dbc.Input(placeholder='输入留言内容:', id='message', style={'width': '100%'}),
width=7,
style={
'padding': 0
}
),
dbc.Col(
dbc.Button('提交', id='submit', color='primary', block=True),
width=2,
style={
'padding': 0
}
)
]
),
style={
'paddingTop': '10px',
'width': '70%',
}
)
],
style={
'height': '800px',
'boxShadow': 'rgb(0 0 0 / 20%) 0px 13px 30px, rgb(255 255 255 / 80%) 0px -13px 30px',
'borderRadius': '10px'
}
),
style={
'paddingTop': '50px'
}
) @app.callback(
Output('history-message', 'children'),
Input('submit', 'n_clicks'),
[State('nickname', 'value'),
State('message', 'value')]
)
def refresh_message_board(n_clicks, nickname, message):
if nickname and message:
submit_new_message(nickname, message) return [
html.Div(
[
html.Strong(record['nickname']),
html.Span(' '),
html.Em(record['pub_datetime'].strftime(format='%Y-%m-%d %H:%M:%S')),
html.Br(),
html.P(record['message_content'])
]
)
for record in fetch_all_message()
] if __name__ == '__main__':
app.run_server(debug=True)

  有关peewee的内容非常丰富,想要完全记住不太现实,大家可以养成多查官网http://docs.peewee-orm.com/en/latest/的习惯,内容非常详细生动,给官方点个赞!

  以上就是本文的全部内容,欢迎在评论区发表你的意见和想法。

(数据科学学习手札120)Python+Dash快速web应用开发——整合数据库的更多相关文章

  1. (数据科学学习手札118)Python+Dash快速web应用开发——特殊部件篇

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  2. (数据科学学习手札102)Python+Dash快速web应用开发——基础概念篇

    本文示例代码与数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的新系列教程Python+Dash快 ...

  3. (数据科学学习手札108)Python+Dash快速web应用开发——静态部件篇(上)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  4. (数据科学学习手札109)Python+Dash快速web应用开发——静态部件篇(中)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  5. (数据科学学习手札112)Python+Dash快速web应用开发——表单控件篇(上)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  6. (数据科学学习手札115)Python+Dash快速web应用开发——交互表格篇(上)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  7. (数据科学学习手札116)Python+Dash快速web应用开发——交互表格篇(中)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  8. (数据科学学习手札117)Python+Dash快速web应用开发——交互表格篇(下)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  9. (数据科学学习手札121)Python+Dash快速web应用开发——项目结构篇

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

随机推荐

  1. WS1008网络损伤测试仪

    WS1008网络损伤测试仪具备高性能的网络损伤仿真功能.冗余链路测试功能和线速流量生成功能,提供了综合性的网络系统测试方案,可充分测试.验证网络系统的抗损伤能力.链路切换能力及数据转发能力.为高可靠性 ...

  2. JVM实战调优(空格引发的服务异常)

    JVM实战调优 问题描述 某一个项目中有一个文字转语音的服务,使用的是科大讯飞的语音转换服务,需要调用三方服务.因其转换服务是一个耗时操作,官方给的demo使用的是 WebSocket 进行数据转换操 ...

  3. golang 二维平面求多重遮挡三角形总面积

    解决问题描述:二维平面有很多三角形错落,可能会相互叠加落在一起,也可能互相远离.目标求出这些三角形的总占地面积. 我最开始想的解决方案是用总面积-总重叠面积 = 总占地面积.后来实现起来发现当面临多次 ...

  4. python网络编程TCP服务多客户端的服务端开发

    #服务多客户端TCP服务端开发 2 #方法说明 3 """ 4 bind(host,port)表示绑定端口号,host是ip地址,ip地址一般不进 行绑定,表示本机的任何 ...

  5. WM_CLOSE WM_QUIT WM_DESTROY 三者的区别

    一 个窗口或者应用程序应该被关闭时发出WM_CLOSE消息,当接收到WM_CLOSE消息时,如果你愿意,向用户提出是否真的退出.你知道让用户作确认或 有错误出现或有什么应该注意的事情发生的时候,往往弹 ...

  6. 攻防世界 reverse 新手练习区

    1.re1 DUTCTF IDA shift+F12 查看字符串 DUTCTF{We1c0met0DUTCTF} 2.game ZSCTF zsctf{T9is_tOpic_1s_v5ry_int7r ...

  7. 实践解析丨Rust 内置 trait:PartialEq 和 Eq

    摘要:Rust 在很多地方使用了 traits, 从非常浅显的操作符重载, 到 Send, Sync 这种非常微妙的特性. Rust 在很多地方使用了 traits, 从非常浅显的操作符重载, 到 S ...

  8. [Design Pattern With Go]设计模式-工厂模式

    这次介绍的设计模式是工厂模式,这是一个比较常见的创建型模式.一般情况下,工厂模式分为三种:简单工厂.工厂方法和抽象工厂,下面慢慢举例介绍下. 简单工厂 考虑一个加密程序的应用场景,一个加密程序可能提供 ...

  9. 什么是事务?事务的四个特性(ACID)?并发事务带来哪些问题?事务隔离级别都有哪些?事务的传播特性

    什么是事务? 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做. 事物的四个 ...

  10. 配置redis 4.0.11 集群

    配置redis 4.0.11 集群 准备redis 软件和redis配置文件 启动Redis服务 /data/soft/redis/src/redis-check-aof --fix /log/red ...