Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2

本文介绍了第一次在Flask框架中操作SQLite3数据库的测试,参考了官网的文档Using SQLite 3 with Flask,直接使用了里面定义

的几个函数:init_db、get_db、close_connection、make_dicts,另外,自己编写了视图(View)函数实现添加、读取操作。

本测试项目的目标

-使用建模文件初始化数据库成功

-连接数据库成功

-关闭数据库成功

-添加数据成功

-读取数据成功,并成功返回到页面

测试步骤

1.建立空的SQLite3数据库文件 和 数据库建模文件

前面一篇关于SQLite3的文章有介绍,使用sqlite3.exe即可;

数据库建模文件,参考SQLite官方文档SQL As Understood By SQLite建立;

下面是我的建模文件内容:

 DROP TABLE IF EXISTS post;
CREATE TABLE post (
id INTEGER PRIMARY KEY AUTOINCREMENT,
body VARCHAR(500) NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

如果原数据库存在,就删除,然后建立新的。

数据表post,包括id、body、created三个字段,其中,body字段为提交的消息,created为消息存放到数据库的时间。

建立好的数据库文件和建模文件放到项目的db文件夹下:

说明,数据库文件和建模文件不一定要放到db文件夹下,也可以放到Flask项目的根目录下(Q:是否可以放到项目之外呢?不建议。),只要程序中把相关路径输入正确即可。

2.编写Flask项目文件main.py(单模块项目)

将文档Using SQLite 3 with Flask中的一些代码拷贝到many.py中。

 from flask import * # 导入flask模块下的所有元素
import sqlite3 # 导入sqlite3模块 app = Flask('Posts') # 建立Flask应用 DATABASE = 'db/posts.db' # 数据库文件地址
DATABASE_INIT_FILE = 'db/init.sql' # 数据库建模文件地址 # init_db()
def init_db(): # 此函数要使用 数据库建模文件 初始化数据库:建立post表(Initial Schemas)。此函数在命令行中使用,仅一次,再次使用会删除数据库中已有数据。
with app.app_context(): # 官网文档说了原因:不是在Web应用中使用,而是在Python Shell中使用时需要此语句(Connect on Demand)。
db = get_db()
with app.open_resource(DATABASE_INIT_FILE, mode='r') as f: # with语句用法!
db.cursor().executescript(f.read()) # 执行建模文件中的脚本
db.commit() # 提交事务 # make_dicts()
def make_dicts(cursor, row): # 将查询返回的数据的转换为字典类型,这样会跟方便使用。此函数会在get_db()函数中用到,赋值给db.row_factory。
return dict((cursor.description[idx][0], value)
for idx,value in enumerate(row)) # get_db()
def get_db(): # 获取数据库连接
db = getattr(g, '_database', None) # g对象时一个Flask应用的公共对象(和request、session一样),用于存储用户的数据——整个应用共享!
if db is None:
db = g._database = sqlite3.connect(DATABASE) # 建立数据库连接
db.row_factory = make_dicts # 转换默认的查询数据类型为字典类型,也可以使用sqlite3.Row
return db # 返回数据库连接,可能返回为None # close_connection()
@app.teardown_appcontext # 这个装饰器用于实现在请求的最后自动关闭数据库连接的功能
def close_connection(exception): # 关闭数据库连接
db = getattr(g, '_database', None)
if db is not None:
db.close()

说明,在誊写代码过程中,把cursor.description写错了,直到最后运行程序才发现了错误。

以上,初始化数据库——只执行一次、获取数据库连接、关闭数据库连接的程序都有了。接下来,建立一个视图函数测试数据库连接、关闭数据库连接是否正常执行。

注意,在此时之前需要再get_db、close_connection函数中添加调试语句,print或者app.logger都可以。

 @app.route('/testdb')
def testdb():
get_db()
return "After test"

然后,启动Flask项目,使用浏览器访问/testdb,检查项目命令行即可看到添加的调试语句——提示错误就继续修改。

3.使用 建模文件 初始化 数据库文件

这个时候需要用到上面的init_db()函数了。

在文档Using SQLite 3 with Flask的Initial Schemas中有介绍,将Flask项目模块的init_db()函数导入,再执行即可。

下面是我的测试情况:成功 按照建模文件 建立 数据表post

注意,在Python Shell执行上面的命令时,需要保证当前目录为Flask项目所在目录。

4.建立测试项目需要视图函数(View functions)

本测试项目需要实现发布消息、展示消息的功能(但并没有做到同一个页面上),因此,建立了三个视图函数来实现目标:

4.1 home()

首页,返回一个模板用于添加post。

此模板文件仅包含静态内容,因此,render_template只有一个参数。

 # path: /
# show posts
@app.route('/')
def home():
return render_template('temp.html')

模板文件主要内容:定义表单,action为“pureadd”

 <form action="pureadd" method="post">
<textarea name="newpost" style="width:200px;height:100px;" maxlength="500"></textarea><br />
<input type="submit" value="添加" />
</form>
<a href="/pureshow">展示帖子</a><br />

页面如下:

4.2 pureadd()

一个单纯地(pure)用于添加一条post到数据库的视图函数,会对参数进行校验、发生错误时会返回错误的信息等。

仅支持POST方法的请求。

此视图的返回信息中还包括跳转到添加页面、展示页面的链接。

 # pure add page for test
@app.route('/pureadd', methods=['POST'])
def pureadd():
# step 1. get the new post and check the data
newp = ''
try:
newp = request.form['newpost']
except:
return 'ERROR: Invalid form parameters!' print('newp = "', newp, '"') newp2 = newp.strip() # 清理post两遍的空格,然后赋值给新变量——此时旧变量没有改变 if newp2 == '':
return 'Warning: New post is empty!<br/>' \
'<a href="/">继续添加</a><br/>' \
'<a href="/pureshow">展示帖子</a><br />' # step 2.write the new post into database
sqlmode = 'INSERT INTO post(body) VALUES(?)' # 添加数据的SQL语句,占位符使用问号(?)。需要注意的是,如果是MySQL,占位符是百分号(%)。
try:
db = get_db()
cursor = db.cursor()
cursor.execute(sqlmode, (newp2,))
cursor.close() # 关闭cursor。Q:是否一定要关闭呢?不关闭有什么影响?
db.commit() # 需要commit,否则,数据不会更新到数据库
except Exception as e:
return '<span style="color:red;">INFO: New post added failed <br/> %s</span><br/>' \
'<a href="/">继续添加</a><br/>' \
'<a href="/pureshow">展示帖子</a><br />' % str(e)
else:
return 'INFO: New post added <br/><pre>[%s]</pre><br/>' \
'<a href="/">继续添加</a><br/>' \
'<a href="/pureshow">展示帖子</a><br />' % newp

成功添加一条数据:

数据库中显示添加的数据:

4.3 pureshow()

此视图函数用于 展示数据库中的数据。

将查询到的数据直接返回到 模板文件showall.html 中。

注意,需要提一下前面get_db()函数中的设置db.row_factory为make_dicts。如果没有这个赋值的话,模板文件的解析数据方式将会改变。

 # pure show page for test
@app.route('/pureshow')
def pureshow():
sqlmode = "SELECT * FROM post ORDER BY created DESC"
rv = []
try:
db = get_db()
cursor = db.execute(sqlmode)
rv = cursor.fetchall()
cursor.close()
except Exception as e:
print(e)
abort(500)
else:
return render_template('showall.html', posts=rv)

模板文件showall.html的主要内容:使用for循环将pureshow()函数返回的内容展示出来

 <div id="postslist">
{% for post in posts %}
<div class="post_item" id="post{{ post.id }}">
{{ post.body }}<br/>
{{ post.created }}
</div>
{% endfor %}
</div>
<a href="/">继续添加</a>

/pureshow页面展示内容如下:

注意,数据库中保存的时间为UTC时间,在实际应用中,展示出来时还需要添加对应的时差。

参考链接

Using SQLite 3 with Flask

廖雪峰官网 之 使用SQLite(关于占位符)

后续

上面的方法很简单,在Flask提供的扩展中,有一个叫做SQLAlchemy的,使用它可以更高效地操作各种数据库,所以,下一步就是学习并使用它了。

官方文档SQLAlchemy in Flask中有介绍,看过一遍了,现在,该实践了。

前面做的项目都是基于单个的模型文件的,后面需要升级:基于package的方式使用Blueprint,这两个是重点啊!

在官网的Tutorial会有关于SQLAlchemy、Blueprint的介绍,也是需要参考的。

Flask,还需要以周计的时间才能熟练使用啊。

自己没有做过完整的Web应用,在URL设计等方面存在一些挑战,因此,这个测试项目才会如此simple。

本来还想实现用户登录、退出等“稍微复杂”的功能的——最初的想法,最后都只能放弃了。

我想,在熟悉了SQLAlchemy、Blueprint后,Web开发的功力会有很大提高的。

对了,还有就是 怎么提供数据接口给前端,比如RESTful API等,都是需要熟练的。

Flask:操作SQLite3(0.1)的更多相关文章

  1. flask, SQLAlchemy, sqlite3 实现 RESTful API 的 todo list, 同时支持form操作

    flask, SQLAlchemy, sqlite3 实现 RESTful API, 同时支持form操作. 前端与后台的交互都采用json数据格式,原生javascript实现的ajax.其技术要点 ...

  2. iOS 数据库sqlite3.0操作--超简单--看我就够啦

    iOS客户端数据存储的方式有很多,下面主要是介绍苹果自带的sqlite3.0的使用方法. 首先导入sqlite3.0的框架.然后导入头文件#import <sqlite3.h>就行了 下面 ...

  3. IOS数据库操作SQLite3使用详解(转)

    iPhone中支持通过sqlite3来访问iPhone本地的数据库.具体使用方法如下1:添加开发包libsqlite3.0.dylib首先是设置项目文件,在项目中添加iPhone版的sqlite3的数 ...

  4. flask 操作mysql的两种方式-sql操作

    flask 操作mysql的两种方式-sql操作 一.用常规的sql语句操作 # coding=utf-8 # model.py import MySQLdb def get_conn(): conn ...

  5. [py]flask操作cookie&django的seesion和cookie机制

    浏览器同源策略(same-origin policy) csrf攻击防御核心点总结 django的cookie和session操作-7天免登录 flask操作cookie&django的see ...

  6. 【delphi】delphi操作sqlite3

    SQLite SQLite是一个老牌的轻量级别的本地文件数据库,完全免费且开源,不需要安装,无须任何配置,当然,这样管理功能就不是很强大了,但是它的主要应用也是在本地数据库,可以说是最简单好用的嵌入式 ...

  7. Flask 中文手册 0.10 文档

    Flask 中文手册 0.10 文档 欢迎使用 Flask 欢迎阅读 Flask 文档. 本文档分为几个部分.我推荐您先从 安装 开始,之后再浏览 快速入门 章节. 教程 比快速入门更详细地介绍了如何 ...

  8. litepal更好的操作sqlite3,配置与基本操作

    litepal更好的操作sqlite3 配置 在app下的build.gradle中加入 创建litepal.xml配置 在app/src/main下面创建assets,新建litepal.xml & ...

  9. iOS: 学习笔记, 使用FMDatabase操作sqlite3

    使用FMDatabase操作sqlite3数据库非常简单和方便 // // main.m // iOSDemo0602_sqlite3 // // Created by yao_yu on 14-6- ...

随机推荐

  1. Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水题

    除非特别忙,我接下来会尽可能翻译我做的每道CF题的题面! Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水题 题面 胡小兔和司公子都认为对方是垃圾. 为了决出谁才是垃 ...

  2. HTML的标签元素分类的区别

    HTML ,即Hyper Text Markup Language 超文本标记语言: 文本:纯字符,如window中的txt文本 超文本:在纯文本中嵌入样式,图片,音频,视频,链接等内容 HTML的基 ...

  3. 【BZOJ2731】三角形覆盖问题

    想象一条平行于\(y\)轴的扫描线,从低往高扫描.如何确定关键高度才能使每两个关键高度之间分割出的图形易于计算呢? 关键高度有:三角形底边高度.三角形上顶点高度.三角形交点的高度. ​ 如此分割,我们 ...

  4. BZOJ 1010 [HNOI2008]toy 玩具装箱

    2017.6.9:经过我的不懈努力,终于把此题A掉了,但上凸和下凸总是那么让人费解…… P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意 ...

  5. ubunto 16.04 lts 源

    http://601502546.blog.163.com/blog/static/2596107620171502517889 国内有很多ubuntu的源,包括:网易源(这个之前用过,速度很快的), ...

  6. 科学计算三维可视化---TraitsUI与Mayavi实例

    TraitsUI与Mayavi实例 一:创建一个简单的TraitsUI与Mayavi实例 from numpy import sqrt,sin,mgrid from traits.api import ...

  7. 科学计算三维可视化---Mlab基础(数据可视化)

    推文:科学计算三维可视化---TVTK库可视化实例 使用相关函数:科学计算三维可视化---Mlab基础(管线控制函数) 一:mlab.pipeline中标量数据可视化 通过持续实例,来感受mlab对数 ...

  8. js加载超时 nginx静态资源

    server { listen ; server_name www.example.com; client_max_body_size 20M; root /xxx/xxx;//项目路径 locati ...

  9. IntelliJ IDEA编码格式设置

    之前一直使用eclipse能够熟悉的设置工程和文件的编码格式,现在换成IntelliJ IDEA设置编码格式的地方有点变化,按照如图所示进行设置: 这里要将Transparent native-to- ...

  10. List(JDK1.7)(1)

    java.util包. 与Set不同, List允许重复的元素.即 e1.equals(e2). 部分方法定义 int size(); 返回列表中元素的个数,如果超过Integer.MAX_VALUE ...