当前位置:网站首页>【Flask】官方教程(Tutorial)-part1:项目布局、应用程序设置、定义和访问数据库
【Flask】官方教程(Tutorial)-part1:项目布局、应用程序设置、定义和访问数据库
2022-07-06 01:26:00 【科皮子菊】
背景
前几篇文章应该大致对flask入了门。实战才是硬道理,根据实战内容不懂什么就需要查阅资料和学习,这样才能对很多概念有更深入的了解。现在就根据官方教程来来总体过一下一个简单的web application demo.
这个教程将引导我们创建一个名为 Flaskr 的基本博客应用程序。用户将能够注册、登录、创建帖子以及编辑或删除他们自己的帖子。您将能够在其他计算机上打包和安装该应用程序。
那么这里也假设读者对python有一定的了解。
虽然它旨在提供一个良好的起点,但本教程并未涵盖 Flask 的所有功能。本教程仅使用 Flask 和 Python 提供的内容。在另一个项目中,您可能决定使用 Extensions 或其他库来简化某些任务。
Flask 很灵活。它不需要您使用任何特定的项目或代码布局。但是,在第一次开始时,使用更有条理的方法会很有帮助。这意味着本教程将需要一些样板文件,但这样做是为了避免新开发人员遇到的许多常见陷阱,并且它创建了一个易于扩展的项目。一旦您对 Flask 更加熟悉,您就可以跳出这种结构,充分利用 Flask 的灵活性。
这个项目代码的官方地址如下:https://github.com/pallets/flask/tree/main/examples/tutorial
本部分主要包括:项目布局、应用程序设置、定义和访问数据库三个部分内容。
程序开发环境还是之前创建的虚拟机以及conda的一个虚拟环境。先在找一个路径创建文件夹:
mkdir flask-tutorial
项目布局
虽然对于flask来说,一个脚本文件就可以开启一个web application,但是随着项目逐渐增加,把各模块分开书写会更加方面开发和管理。针对这种情况,在flask-tutorial文件夹下有如下类似的布局(官方文档):
/home/user/Projects/flask-tutorial
├── flaskr/
│ ├── __init__.py
│ ├── db.py
│ ├── schema.sql
│ ├── auth.py
│ ├── blog.py
│ ├── templates/
│ │ ├── base.html
│ │ ├── auth/
│ │ │ ├── login.html
│ │ │ └── register.html
│ │ └── blog/
│ │ ├── create.html
│ │ ├── index.html
│ │ └── update.html
│ └── static/
│ └── style.css
├── tests/
│ ├── conftest.py
│ ├── data.sql
│ ├── test_factory.py
│ ├── test_db.py
│ ├── test_auth.py
│ └── test_blog.py
├── venv/
├── setup.py
└── MANIFEST.in
除此之外,该项目可以就行安装一个python包一样安装到系统中,启动也是比较方案的以及还增加了一个测试模块。可谓是麻雀虽小五脏俱全呀。
如果使用git进行版本控制的话,应该还会有git相关的目录等。当然,刚才说到这个项目可以像安装python包一样,那么在安装的同时,会生成一些文件,这个也是当前目录中没有的内容哦。
然后我们可以看到,项目的静态文件夹,templates文件夹都在flaskr目录下。
应用程序设置
一个flask应用本质上来说是Flask这个类的一个实例。关于这个应用的所有,例如配置信息、URL等都需要注册到这个类中。创建 Flask 应用程序最直接的方法是直接在代码顶部创建一个全局 Flask 实例,例如下面的一个实例(hello.py):
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
虽然这在某些情况下简单且有用,但随着项目的发展,它可能会导致一些棘手的问题。
我们可以在函数内部创建它,而不是全局创建 Flask 实例。此功能称为应用 application factory
。应用程序需要的任何配置、注册和其他设置都将在函数内部进行,然后将返回应用程序。这种方式还是很有意思的,我们接着看。
这个Application Factory
在此之前使用pycharm连接一下开发环境。
现在就要开始写代码了,是不是很期待呀。在项目路径下再创建一个packageflaskr
,如果是使用pycharm创建,会自动创建__init__.py
文件,如下:
这个Application Factory的主要内容就在这个__init__.py
文件中,现在为其添加如下内容:
import os
from flask import Flask
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
if test_config is None:
# load the instance config, if it exists, when not testing
app.config.from_pyfile('config.py', silent=True)
else:
# load the test config if passed in
app.config.from_mapping(test_config)
# ensure the instance folder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
# a simple page that says hello
@app.route('/hello')
def hello():
return 'Hello, World!'
return app
上面代码都表示什么意思呢?
create_app
是一个应用工厂函数;app=Flask(__name__, instance_relative_config=True)
, 创建Flask实例,__name__
是当前Python模块的名称。app是通过它去定位以及去设置一些路径的。instance_relative_config=True
告诉app程序配置文件是相对于实例文件夹的,就可以方便读取app的配置文件。实例文件夹位于 flaskr 包之外,可以保存不应提交给版本控制的本地数据,例如配置机密和数据库文件。
app.config.from_mapping()
设置应用程序将使用的一些默认配置:SECRET_KEY
,Flask 和扩展使用 SECRET_KEY 来保证数据安全。它设置为 ‘dev’ 以便在开发期间提供方便的值,但在部署时应该用随机值覆盖它。DATABASE
:SQLite 数据库文件将被保存的路径。它位于app.instance_path
下,这是 Flask 为实例文件夹选择的路径。
app.config.from_pyfile()
:使用从实例文件夹中的 config.py 文件(如果存在)获取的值覆盖默认配置。例如,在部署时,这可以用来设置一个真正的 SECRET_KEY。test_config
:它可以传递给工厂,并将用于代替实例配置。这样您将在本教程后面编写的测试可以独立于您已配置的任何开发值进行配置。
os.makedirs()
:确保app.instance_path
存在。Flask 不会自动创建实例文件夹,但需要创建它,因为项目将在那里创建 SQLite 数据库文件。@app.route()
:创建一个简单的路由,以便在进入教程的其余部分之前查看应用程序的工作情况。它在URL /hello
和返回响应的函数之间创建连接,即字符串“Hello, World!”。
app的运行
现在我们可以使用flask
命令来运行应用了。在终端运行时,需要告诉Flask 在哪找到我们的application,通过设置application为开发模式,方便我们去调试,开发模式会在页面引发异常时显示交互式调试器,并在您更改代码时重新启动服务器。您可以让它继续运行,然后按照教程重新加载浏览器页面。。需要注意的是,在终端执行运行命令时,需要在flask-tutorial
文件夹下。
为了能够让宿主机能够访问这个服务,我在服务运行中添加了--host=0.0.0.0
参数。运行过程如下:
如果出现端口占用情况,可以参考:【Centos7】防火墙(firewall)常用命令总结
定义和访问数据库
一个简单的application已经可以运行了。我们书写的项目是一个博客系统,那么就需要数据去存储博客,用户信息内容。为了是的这个系统比较简单,使用的是一个比较轻量级的数据库SQLite(python sqlite3)。
SQLite 很方便,因为它不需要设置单独的数据库服务器并且内置于 Python。但是,如果并发请求尝试同时写入数据库,它们会因为每次写入顺序发生而变慢。小型应用程序不会注意到这一点。一旦你变大了,你可能想要切换到不同的数据库。
这个小项目不会深入介绍sqlite的使用,可以自行网上查阅相关内容。
连接数据库
使用 SQLite 数据库(和大多数其他 Python 数据库库)时要做的第一件事是创建到它的连接。任何查询和操作都是使用连接执行的,连接在工作完成后关闭。
在 Web 应用程序中,此连接通常与请求相关联。它是在处理请求时创建的,并在发送响应之前关闭。
现在我们在flaskr文件下创建db.py文件,并在该文件中书写如下代码:
import sqlite3
import click
from flask import current_app, g
from flask.cli import with_appcontext
def get_db():
if 'db' not in g:
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
return g.db
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db.close()
针对上面的代码,说明如下:
g
:它是一个特殊对象,对于每个请求都是唯一的。它用于存储在请求期间可能被多个函数访问的数据。如果在同一请求中第二次调用 get_db,则连接将被存储并重用,而不是创建新连接。current_app
:它是另一个特殊对象,它指向处理请求的 Flask 应用程序。由于我们使用了application factory,因此在编写其余代码时没有应用程序对象。get_db
将在应用程序创建并正在处理请求时调用,因此可以使用current_app
。sqlite3.connect()
:它建立与 DATABASE 配置键指向的文件的连接。该文件不必存在,并且在您稍后初始化数据库之前不会存在。sqlite3.Row
:告诉连接返回行为类似于 dicts 的行。这允许按名称访问列。close_db()
:通过检查是否设置了g.db
来检查是否创建了连接。如果连接存在,则将其关闭。再往下,我们将告诉应用程序有关应用程序工厂中的close_db
函数,以便在每次请求后调用它。
创建表
在 SQLite 中,数据存储在表和列中。这些需要在您存储和检索数据之前创建。Flaskr 会将用户存储在 user 表中,并将帖子存储在 post 表中。使用创建空表所需的 SQL 命令创建一个文件flaskr/schema.sql:
DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS post;
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL
);
CREATE TABLE post (
id INTEGER PRIMARY KEY AUTOINCREMENT,
author_id INTEGER NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
title TEXT NOT NULL,
body TEXT NOT NULL,
FOREIGN KEY (author_id) REFERENCES user (id)
);
下面在db.py中增加一些sql运行的命令。
def init_db():
db = get_db()
with current_app.open_resource('schema.sql') as f:
db.executescript(f.read().decode('utf8'))
@click.command('init-db')
@with_appcontext
def init_db_command():
"""Clear the existing data and create new tables."""
init_db()
click.echo('Initialized the database.')
需要说明的是:
open_resource()
会打开flaskr
目录下的一个文件,这很有用,因为在以后部署应用程序时不一定知道该位置在哪里。get_db
会返回一个数据库连接,用于执行从文件中读取的命令。click.command()
定义一个名为 init-db 的命令行命令,它调用 init_db 函数并向用户显示成功消息。这个在后面初始化数据库时就可以看到。
应用程序的注册
close_db
和 init_db_command
函数需要在应用实例中注册;否则,它们将不会被应用程序使用。但是,由于您使用的是工厂函数,因此在编写函数时该实例不可用。那么就需要编写一个接受应用程序并进行注册的函数。 需要在db.py中添加如下函数:
def init_app(app):
app.teardown_appcontext(close_db)
app.cli.add_command(init_db_command)
程序说明:
app.teardown_appcontext()
告诉 Flask 在返回响应后进行清理时调用该函数。app.cli.add_command()
添加一个可以使用 flask 命令调用的新命令。
从工厂导入并调用此函数。在返回应用程序之前,将新代码放在工厂函数的末尾。操作如下:
def create_app():
app = ...
# existing code omitted
from . import db
db.init_app(app)
return app
初始化数据库文件
现在 init-db
已经注册到应用程序中,可以使用 flask 命令调用它,类似于之前的 run 命令。
注:如果您仍在从上一页运行服务器,您可以停止服务器,或在新终端中运行此命令。如果您使用新终端,请记住更改到您的项目目录并按照之前的方式激活 。您还需要设置 FLASK_APP 和 FLASK_ENV,与之前记得方式相同。
下面我们在终端运行这个命令去初始化数据库:flask init-db
执行完之后,我们可以在flaskr的instance文件夹下生成一个flaskr.sqlite文件。
也可以将数据库文件下载到本机,然后使用pycharm的数据库查看工具查看表结构,如下:
这个命令行命令flask init-db
与db.py中 init_db_command()
函数是绑定的,这个函数需要注册到app这个应用中,因为这个函数需要使用app应用中的一些配置,如:schema.sql文件所在的文件夹等。
边栏推荐
- Yii console method call, Yii console scheduled task
- Tcpdump: monitor network traffic
- False breakthroughs in the trend of London Silver
- File upload vulnerability test based on DVWA
- MUX VLAN configuration
- [understanding of opportunity-39]: Guiguzi - Chapter 5 flying clamp - warning 2: there are six types of praise. Be careful to enjoy praise as fish enjoy bait.
- CocoaPods could not find compatible versions for pod 'Firebase/CoreOnly'
- 037 PHP login, registration, message, personal Center Design
- WordPress collection plug-in automatically collects fake original free plug-ins
- A picture to understand! Why did the school teach you coding but still not
猜你喜欢
Introduction to robotics I. spatial transformation (1) posture, transformation
A picture to understand! Why did the school teach you coding but still not
ADS-NPU芯片架构设计的五大挑战
【已解决】如何生成漂亮的静态文档说明页
Leetcode skimming questions_ Verify palindrome string II
After 95, the CV engineer posted the payroll and made up this. It's really fragrant
Yii console method call, Yii console scheduled task
Leetcode skimming questions_ Sum of squares
3D model format summary
Opinions on softmax function
随机推荐
MYSQL---查询成绩为前5名的学生
[Arduino syntax - structure]
MATLB | real time opportunity constrained decision making and its application in power system
How to get the PHP version- How to get the PHP Version?
Leetcode 208. Implement trie (prefix tree)
在产业互联网时代,将会凭借大的产业范畴,实现足够多的发展
【已解决】如何生成漂亮的静态文档说明页
SPIR-V初窥
普通人下场全球贸易,新一轮结构性机会浮出水面
Interview must brush algorithm top101 backtracking article top34
General operation method of spot Silver
【SSRF-01】服务器端请求伪造漏洞原理及利用实例
How does the crystal oscillator vibrate?
MATLB|实时机会约束决策及其在电力系统中的应用
ORA-00030
黄金价格走势k线图如何看?
JVM_ 15_ Concepts related to garbage collection
Recommended areas - ways to explore users' future interests
JMeter BeanShell的基本用法 一下语法只能在beanshell中使用
【全網最全】 |MySQL EXPLAIN 完全解讀