零基础入门python web框架Flask开发

Flask框架是Python开发的一个基于Werkzeug和Jinja 2的web开发微框架,它的优势就是极其简洁,但又非常灵活,而且容易学习和应用。因此Flask框架是Python新手快速开始web开发最好的选择,此外,使用Flask框架的另一个好处在于你可以非常轻松地将基于Python的机器学习算法或数据分析算法集成到web应用中。

如果希望深入学习Flask Web开发,推荐这个教程:
深入浅出Flask

1、可以用Flask框架做什么

从博客应用到克隆一个facebook或者twitter,理论上你可以用Flask做任何事情。有很多库可以直接使用,例如flask-sockets,flask-google-maps等,而且Flask框架支持MySQL、Postgresql、MongoDB等诸多数据库。

我能想到的一些可以用Flask框架实现的web应用类型:博客应用、聊天应用、仪表盘应用、RESTAPI、管理页面、邮件服务等。

安装Flask

使用pip安装Flask:

$ pip install flask

2、Hello,World

创建一个文件app.py,然后只需要几个简单的步骤,就可以写出Flask版本的Hello World

  1. 引入Flask类
from flask import Flask
  1. 创建Flask对象,我们将使用该对象进行应用的配置和运行:
app = Flask(__name__)

name 是Python中的特殊变量,如果文件作为主程序执行,那么__name__变量的值就是__main__,如果是被其他模块引入,那么__name__的值就是模块名称。

  1. 编写主程序

在主程序中,执行run()来启动应用:

if __name__ =="__main__":
    app.run(debug=True, port=8080)

改名启动一个本地服务器,默认情况下其地址是localhost:5000,在上面的代码中,我们使用关键字参数port将监听端口修改为8080。

  1. 路由

使用app变量的route()装饰器来告诉Flask框架URL如何触发我们的视图函数:

@app.route('/')
def hello_world():
    return 'Hello, World!'

上面的标识,对路径'/'的请求,将转为对hello_world()函数的调用。很直白,对吧?

  1. 运行

现在,让我们完整地看一下app.py的整个代码:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

if __name__ =="__main__":
    app.run(debug=True,port=8080)

然后运行起来:

$ python app.py

你应该会看到如下输入:

* Serving Flask app "app" (lazy loading)
* Environment: production
* Debug mode: on
* Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 770-937-705

现在就可以打开浏览器访问http://127.0.0.1:8080/了:

hello world

3、使用HTML模板

首先我们看看如何原始的HTML代码插入Flask应用:

from flask import Flask
app = Flask(__name__)


@app.route('/greet')
def greet():
    user = {'username': 'John', 'age': "20"}
    return '''
<html>
    <head>
        <title>Templating</title>
    </head>
    <body>
        <h1>Hello, ''' + user['username'] + '''!, you’re ''' + user['age'] + ''' years old.</h1>
    </body>
</html>'''


if __name__ == '__main__':
app.run(debug = True,port=8080)

在上面的代码中,我们使用拼接的HTML字符串来展示user字典的数据。现在访问http://127.0.0.1:8080/greet

hello world

拼接HTML字符串非常容易出错,因此Flask使用Jinja 2模板引擎来分离数据逻辑和展示层。

我们将模板文件按如下路径放置:

Apps folder
/app.py
templates
   |-/index.html

使用模板时,视图函数应当返回render_template()的调用结果。例如下面的代码片段渲染模板index.html,并将渲染结果作为视图函数的返回值:

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/hello')
def hello():
    return render_template('index.html', name="Alex")

if __name__ == '__main__':
    app.run(debug = True)

在上面的代码中,模板文件index.html依赖于变量name,其内容如下:

<html>
<body>
  {% if name %}
    <h2>Hello {{ name }}.</h2>
  {% else %}
    <h2>Hello.</h2>
  {% endif %}
 </body>
</html>

模板文件的语法扩充了HTML,因此可以使用变量和逻辑。

在浏览器中访问http://127.0.0.1:8080/hello/alex

hello world

4、使用表单

每个web应用都需要使用表单来采集用户数据。现在让我们使用Flask框架创建一个简单的表单来收集用户的基本信息,例如名称、年龄、邮件、兴趣爱好等,我们将这个模板文件命名为bio_form.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <h1>Bio Data Form</h1>
    <form action="showbio">
        <label>Username</label>
        <input type="name" name="username"><br>
        <label>Email</label>
        <input type="email" name="email"><br>
        <label>Hobbies</label>
        <input type="name" name="hobbies"><br>
        <input type="submit" name="">
    </form>
</body>
</html> 

视图函数bio_data_form同时支持POST和GET请求。GET请求将渲染bio_form.html模板,而POST请求将重定向到showbio

@app.route('/form', methods=['POST', 'GET'])
def bio_data_form():    
    if request.method == "POST":
        username = request.form['username']        
        age = request.form['age']        
        email = request.form['email']        
        hobbies = request.form['hobbies']        
        return redirect(url_for('showbio',                              
                                username=username,
                                age=age,
                                email=email,   
                                hobbies=hobbies))    
    return render_template("bio_form.html")

下面是showbio的实现:

@app.route('/showbio', methods=['GET'])
def showbio():    
    username = request.args.get('username')    
    age = request.args.get('age')    
    email = request.args.get('email')    
    hobbies = request.args.get('hobbies')    
    return render_template("show_bio.html",
                           username=username,                         
                           age=age,                          
                           email=email,                         
                           hobbies=hobbies)

以及show_bio.html的内容:

<!DOCTYPE html>
<html>
<head>
    <title>Bio-Data Details</title>
</head>
<body>
    <h1>Bio-Data Details</h1>
    <hr>
    <h1>Username: {{ username }}</h1>
    <h1>Email: {{ email }}</h1>
    <h1>Hobbies: {{ hobbies }}</h1>
</body>
</html>

5、数据库集成:使用SQLAlchemy

Flask不能直接连接数据库,需要借助于ORM(Object Relational Mapper)。在这一部分,我们将借助于SQLAlchemy使用Postgres数据库。

  1. 安装Flask-SQLAlchemy和Postgres

首先安装flask-sqlalchemy:

$ pip install flask-sqlalchemy

然后从官方下载并安装postgres:https://postgresapp.com/

  1. 创建数据库

在终端中使用下面的命令创建一个appdb数据库:

$ createdb appdb
  1. 更新应用配置

修改app.config,添加数据库相关的配置信息:

app.config['DEBUG'] = True
app.config['SQLALCHEMY_DATABASE_URI']='postgresql://localhost/appdb'
SQLALCHEMY_TRACK_MODIFICATIONS = True
db = SQLAlchemy(app)

然后在代码中就可以使用这些配置数据了:

from flask import Flask, request, render_template
from flask_sqlalchemy import SQLAlchemy

# Settings
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/appdb'
db = SQLAlchemy(app)

@app.route('/')
def hello_world():
    return 'Hello, World!'

if __name__ == '__main__':
    app.run()

现在,让我们创建第一个模型(Model)。所有模型的基类是db.Model,使用Column来定义数据列:

class Post(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    title = db.Column(db.String(80), unique=True)
    post_text = db.Column(db.String(255))
    
    def __init__(self, title, post_text):
        self.title = title
        self.post_text = post_text

在代码中使用模型:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/testdb'

db = SQLAlchemy(app)


class Post(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    title = db.Column(db.String(80), unique=True)
    post_text = db.Column(db.String(255))

    def __init__(self, title, post_text):
        self.title = title
        self.post_text = post_text


@app.route('/')
def index():
    return "Hello World"


app = Flask(__name__)

if __name__ == "__main__":
    app.run()

6、模型-数据同步

使用ORM时,需要执行迁移操作以便在模型和持久化数据之间保持同步。我们使用Flask-Migrate这个扩展来完成该任务。

首先安装:

$ pip install flask-migrate
$ pip install flask_script

然后在代码中引入:

from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand

进行必要的配置:

migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)

运行管理器:

if __name__ == '__main__':
    manager.run()

完整的代码如下:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/appdb'

db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)


class Post(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    title = db.Column(db.String(80), unique=True)
    post_text = db.Column(db.String(255))

    def __init__(self, title, post_text):
        self.title = title
        self.post_text = post_text


@app.route('/')
def index():
    return "Hello World"


if __name__ == "__main__":
    manager.run()

使用如下的命令初始化Alembic:

$ python app.py db init
Creating directory /Users/Vihar/Desktop/flask-databases/migrations ... done
...
...
...
Generating /Users/Vihar/Desktop/flask-databases/migrations/alembic.ini ... done

执行第一个迁移任务:

$ python app.py db migrate
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'post'

Generating /Users/Vihar/Desktop/flask-databases/migrations/versions/ed3b3a028447_.py ... done

一旦上述命令执行完毕,我们的数据表就会创建成功。现在更新数据库:

$ python app.py db upgrade
orm

汇智网翻译整理,转载请标明出处。原文链接:Flask框架web开发:零基础入门

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,348评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,122评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,936评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,427评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,467评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,785评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,931评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,696评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,141评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,483评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,625评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,291评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,892评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,492评论 2 348

推荐阅读更多精彩内容