首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python全栈(七)Flask框架之1.Flask简介与URL和视图介绍

Python全栈(七)Flask框架之1.Flask简介与URL和视图介绍

作者头像
cutercorley
发布2020-07-23 16:31:47
7780
发布2020-07-23 16:31:47
举报

Flask简介与URL和视图介绍

  • 一、虚拟环境介绍
    • 1.虚拟环境与全局环境
    • 2.为什么需要虚拟环境
    • 3.虚拟环境的安装和简单操作
      • pipenv的安装
      • 创建虚拟环境
      • pipfile和pipfile.lock
  • 二、Flask介绍
    • 1.Flask简介
    • 2.第一个Flask程序
  • 三、设置Debug模式
  • 四、配置与配置文件
    • 1.直接硬编码
    • 2.通过update()方法
    • 3.通过from_object()方法
    • 4.通过from_pyfile()方法
  • 五、URL与函数的映射

一、虚拟环境介绍

1.虚拟环境与全局环境

有时候安装了一个Python库,可能在IDE如PyCharm中不能使用,这是因为: 通过pip安装的库默认一般在全局环境中,而PyCharm一般会默认创建虚拟环境,所以两者的环境不一致,导致安装的包不能正常导入使用,解决办法有2种:

  • 在PyCharm虚拟环境中安装库,使库位于虚拟环境中
  • 将PyCharm的环境设置为全局环境,即我们通常使用的Python,设置为Python的安装目录即可 设置示意如下:
PyCharm 设置编译环境
PyCharm 设置编译环境

2.为什么需要虚拟环境

一般情况下,Python第三方库安装是直接通过pip install xxx的方式进行安装的,这样安装会将库安装到系统级的Python环境中。 但是有时可能会面临这样的问题:如果现在用Django 1.10.x写了个网站,但是同时有一个Django 0.9开发的项目需要维护,并且有可能Django 1.10不再兼容Django 0.9的一些语法了,这就需要同时拥有Django 1.10和Django 0.9两套环境,我们可以通过虚拟环境来解决这个问题。

3.虚拟环境的安装和简单操作

虚拟环境管理有很多工具,这里我选择pipenv。

pipenv的安装

命令:

  • Windows下
pip install pipenv
  • Mac下
brew install pipenv
  • Linux下
pip install pipenv

创建虚拟环境

安装之后即可创建虚拟环境。 创建虚拟环境使用命令pipenv shell,如下:

pipenv shell
pipenv shell

出现图中所标提示Flask_Framework-rL0Lvhvz及说明安装成功,此时再运行pip list可以看到虚拟环境中默认安装的库:

Package    Version
---------- -------
pip        20.0.2
setuptools 46.1.3
wheel      0.34.2

不能同时使用全局环境和虚拟环境的库,只能选择使用其中一个。 虚拟环境默认会安装到系统盘(C盘)下的当前用户目录下的 .virtualenvs 目录下,如果想指定安装到其他目录,可以设置系统环境变量,在系统变量中添加变量,变量名为WORKON_HOME,值为需要指定安装的目录,示意如下:

pipenv 设置安装环境变量
pipenv 设置安装环境变量

此时再安装虚拟环境,即会安装到指定的目录下。

虚拟环境安装好之后,需要在PyCharm中设置虚拟环境为当前创建的虚拟环境,即定位选择虚拟环境下的python.exe可执行文件,方法与前面相同。

需要在虚拟环境中通过命令pip install flask安装Flask,再查看安装的库,结果如下:

Package      Version
------------ -------
click        7.1.1
Flask        1.1.2
itsdangerous 1.1.0
Jinja2       2.11.1
MarkupSafe   1.1.1
pip          20.0.2
setuptools   46.1.3
Werkzeug     1.0.1
wheel        0.34.2

显然,在安装flask时,安装了存在依赖关系的其他库。 如果电脑中同时拥有Python3和Python2,可以指定版本:

pipenv --three  # 泛指Python3的版本 
pipenv --two    # 泛指Python2的版本 
pipenv --python 3.7 # 指定Python具体版本

虚拟环境管理

pipenv shell    # 如果虚拟环境已存在则进入虚拟环境,否则创建并进入虚拟环境
exit            # 退出虚拟环境
pipenv --rm     # 删除整个环境  不会删除pipfile

pipfile和pipfile.lock

在创建虚拟环境后,虚拟环境目录下会生成pipfile文件,内容如下:

[[source]] name = “pypi” url = “https://pypi.org/simple” verify_ssl = true [dev-packages] [packages] requests = “*” django = “*” [requires] python_version = “3.7”

参数说明:

  • url 可以指定国内pip源,在默认情况使用国外源下载库可能会很慢
  • dev-packages 开发环境
  • packages 生产环境
  • django = “*” *表示最新版本
  • requires Python版本

pipfile.lock详细记录环境依赖,并且使用了Hash算法以保证完整的对应关系。

如果需要将安装的库记录到Pipfile中,可以使用pip install --dev 库名将库安装到开发环境。

在虚拟环境中用run参数运行项目示例如下:

pipenv run python manage.py runserver

pipenv有一个缺点: lock不稳定而且时间非常长,所以安装包的时候记得加上--skip-lock,如下:

pipenv install django --skip-lock

最后开发完成要提交到仓库的时候再执行pipenv lock命令。

二、Flask介绍

1.Flask简介

flask是一款非常流行的Python Web框架,诞生于2010年,作者是Armin Ronacher,这个项目最初只是作者在愚人节的一个玩笑,后来由于非常受欢迎,逐渐成为一个正式的项目。 flask自2010年发布第一个版本以来,大受欢迎,深得开发者的喜爱,并且在多个公司已经得到了应用,flask能如此流行的原因,可以分为以下几点:

  • 微框架、简洁,只做它需要做的,灵活度非常高,给开发者提供了很大的扩展性。 Flask不会帮开发者做太多的决策,一切都可以按照自己的意愿进行更改。
    • 使用Flask开发数据库的时候,具体是使用SQLAlchemy还是MongoEngine,选择权完全掌握在开发者自己的手中。区别于Django,Django内置了非常完善和丰富的功能,并且如果想替换成开发者想要的,要么不支持,要么非常麻烦。
    • 把默认的Jinija2模板引擎替换成其他模板引擎都是非常容易的。
  • Flask和相应的插件写得很好。
  • 开发效率非常高,比如使用SQLAlchemy的ORM操作数据库可以节省开发者书写大量sql的时间。

2.第一个Flask程序

from flask import Flask

# 传入__name__初始化一个Flask实例
app = Flask(__name__)


# 装饰器,将当前路由映射到指定函数
@app.route('/')
def hello_world():
    return 'hello world'


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

打印:

 * Serving Flask app "first_flask" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

此时已经创建服务,在浏览器中打开http://127.0.0.1:5000/即可看到:

flask first program
flask first program

并且在开启的服务状态栏下会看到请求的记录,如:

127.0.0.1 - - [09/Apr/2020 07:54:10] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [09/Apr/2020 07:54:10] "GET /favicon.ico HTTP/1.1" 404 -

说明:

  • @app.route('/')装饰器映射URL和执行的函数。这个设置将URL映射到指定的函数上,例中指定当前路由为根目录,如果为根目录时也可以不写 /,但是尽量写上以示区别。
  • app.run()是让flask项目运行起来,可以指定主机号和端口号。 默认的host是127.0.0.1,port为5000host=0.0.0.0可以让其他电脑也能访问到该网站,port指定访问的端口。

三、设置Debug模式

默认情况下flask不会开启DEBUG模式,开启DEBUG模式后,flask会在每次保存代码的时候自动的重新载入代码,并且如果代码有错误,会在终端提示。 在hello_world()函数中加入错误代码进行测试:

from flask import Flask

app = Flask(__name__)


# 装饰器,将当前路由映射到指定函数
@app.route('/')
def hello_world():
    result = 1 / 0
    return 'hello world'


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

重新运行开启服务后,会发现:

flask server error
flask server error

在日志中也会发现报错:

[2020-04-09 08:07:17,881] ERROR in app: Exception on / [GET]
Traceback (most recent call last):
  File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\_compat.py", line 39, in reraise
    raise value
  File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "xxx/first_flask.py", line 9, in hello_world
    result = 1 / 0
ZeroDivisionError: division by zero
127.0.0.1 - - [09/Apr/2020 08:07:17] "GET / HTTP/1.1" 500 -

这与显然很麻烦,每次修改之后必须重新运行,而且错误信息在日志中才能看到。 我们可以开启Debug模式,这样每次修改代码后都会载入代码重新运行,并且代码有问题时会显示错误信息。

开启Debug模式有几种方式:

  • run()方法中设置debug参数为True
if __name__ == '__main__':
    app.run(debug=True)
  • 设置app对象实例的属性为True
if __name__ == '__main__':
    app.debug = True
    app.run()
  • 通过配置参数config设置
if __name__ == '__main__':
    app.config.update(DEBUG=True)
    app.run()

config是继承自字典类型的,所以可以使用字典的update()方法。

开启Debug模式测试如下:

from flask import Flask

app = Flask(__name__)


# 装饰器,将当前路由映射到指定函数
@app.route('/')
def hello_world():
    result = 1 / 0
    return 'hello world'


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

此时再看网页:

flask error debug
flask error debug

并且控制台中也会提示已开启Debug模式:

 * Serving Flask app "first_flask" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 313-629-160
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

现在每次修改完代码保存之后,都会自动加载代码重启服务,不需要再手动关闭服务再重启了。

在开启了DEBUG模式后,当程序有异常会进入错误堆栈模式,第一次点击某个堆栈想查看变量值的时候,页面会弹出一个对话框,提示输入PIN值,比如在刚刚启动的项目中的PIN值为313-629-160,输入这个值后,Werkzeug会把这个PIN值作为cookie的一部分保存起来,并在8小时后过期,8小时内不需要再输入PIN值。这样做的目的是为了提高安全性,让调试模式下的攻击者更难攻击到本站。

此时可以在报错的网页中进行一些简单的Debug,使用控制台提供的PIN操作示意如下:

flask webpage debug
flask webpage debug

Debug模式是在开发环境中开启的,开发完成上线之后要关闭Debug模式,因为DEBUG模式会带来非常大的安全隐患。

四、配置与配置文件

Flask项目的配置,都是通过app.config对象来进行配置的。 比如要配置一个项目处于DEBUG模式下,那么可以使用app.config['DEBUG'] = True来进行设置,那么Flask项目将以DEBUG模式运行。 在Flask项目中,有四种方式进行项目的配置。

1.直接硬编码

app = Flask(__name__)
app.config['DEBUG'] = True

硬编码的方式不灵活,不便于进行复用。

2.通过update()方法

因为app.config是flask.config.Config的实例,而Config类是继承自dict,因此可以通过update()方法进行配置。

app.config.update(
   DEBUG=True,
   SECRET_KEY='...'
)

3.通过from_object()方法

如果配置项特别多,可以把所有的配置项都放在一个模块中,然后通过加载模块的方式进行配置,假设有一个settings.py模块,专门用来存储配置项的,此你可以通过app.config.from_object()方法进行加载,并且该方法既可以接收模块的的字符串名称,也可以模块对象。 有两种形式:

# 1. 通过模块字符串
app.config.from_object('settings')
# 2. 通过模块对象
import settings
app.config.from_object(settings)

添加配置文件后,将配置项都放入该文件中,其他文件直接引用该配置文件中的配置项,提高了代码的复用性、降低了耦合度,同时,在配置文件中修改了配置项时,其他代码中均不需要修改,从而提高了代码的灵活性。 新建config.py文件,添加一些配置项如下:

# 设置Debug模式为True
DEBUG = True

# 指定HOST
HOST = '127.0.0.1'

在flask文件中导入:

from flask import Flask
import config

app = Flask(__name__)


# 装饰器,将当前路由映射到指定函数
@app.route('/')
def hello_world():
    result = 1 / 0
    return 'hello world'


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

再运行,也能开启Debug模式。 也可以通过字符串形式导入:

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

此时不需要再导入config模块。

4.通过from_pyfile()方法

app.config.from_pyfile()方法传入一个文件名,通常是以.py结尾的文件,但也不限于只使用.py后缀的文件。 通过导入Python文件的形式导入配置文件:

if __name__ == '__main__':
    app.config.from_pyfile('config.py')
    app.run()

from_pyfile()方法有一个silent参数,设置为True时,如果配置文件不存在也不会报错; 不仅支持Python格式的配置文件,也支持.ini等格式。

五、URL与函数的映射

从前面的例子中,我们可以看到,一个URL要与执行函数进行映射,使用的是@app.route装饰器。 @app.route装饰器中,可以指定URL的规则来进行更加详细的映射,比如现在要映射一个文章详情的URL,文章详情的URL是/article/id/,id有可能为1、2、3…,那么可以通过以下方式:

@app.route('/article/<id>')
def article(id):
   return '%s article detail' % id

其中,尖括号是固定语法,表示地址中传入的参数,默认的数据类型是字符串。 如果需要限制参数类型,则要写成限制类型:变量名,其中限制类型包括以下几种:

  • string 默认的数据类型,接受任何没有斜杠/的字符串。
  • int 整型。
  • float 浮点型。
  • path 和string类似,但是可以传递斜杠/。
  • uuid uuid类型的字符串。
  • any 可以同时指定多种路径。

新增路由域函数映射测试:

from flask import Flask


app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/corley')
def hello_corley():
    return '这是我的第一个Flask页面'

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

显示:

flask url view map
flask url view map

显然,在地址中访问http://127.0.0.1/corley可以访问到,因为在flask中已经定义了。 同时还可以动态传入参数:

from flask import Flask


app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/corley')
def hello_corley():
    return '这是我的第一个Flask页面'

@app.route('/list/<aid>')
def article_list(aid):
    return '这是第{}篇文章'.format(aid)

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

显示:

flask url view map params
flask url view map params

显然,因为未定义 /list 所以不能访问http://127.0.0.1:5000/list; 此时已经可以根据传入的参数动态显示视图,但是并未对数据类型进行限制,可以增加对数据类型的限制:

from flask import Flask


app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/corley')
def hello_corley():
    return '这是我的第一个Flask页面'

@app.route('/list/<int:aid>')
def article_list(aid):
    return '这是第{}篇文章'.format(aid)

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

显示:

flask url view map params int
flask url view map params int

显然,此时参数只能是整型数字了。

一般情况下参数中不能含有 /,要想含有 /,必须限制为path类型,除了此区别,path与string类型基本一样。 示例如下:

from flask import Flask


app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/corley')
def hello_corley():
    return '这是我的第一个Flask页面'

@app.route('/list/<int:aid>')
def article_list(aid):
    return '这是第{}篇文章'.format(aid)

@app.route('/list/<path:aid>')
def comment_list(aid):
    return '这是第{}个评论'.format(aid)

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

显示:

flask url view map params path
flask url view map params path

显然,如果参数为数字时,匹配article_list(aid)函数,如果为字符串类型或者参数中含有 / 时匹配comment_list(aid)函数。

访问两个路径用同一个函数可以用any来限制,示例如下:

from flask import Flask


app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/corley')
def hello_corley():
    return '这是我的第一个Flask页面'

@app.route('/list/<int:aid>')
def article_list(aid):
    return '这是第{}篇文章'.format(aid)

@app.route('/list/<path:aid>')
def comment_list(aid):
    return '这是第{}个评论'.format(aid)

@app.route('/<any(notice,follow):url_path>/')
def message(url_path):
    if url_path == 'notice':
        return '当前路径是notice'
    else:
        return '当前路径是follow'


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

显示:

flask url view map params any
flask url view map params any

此时定义路由时需要在路径最后添加 / 才能正常访问,如/<any(notice,follow):url_path>/

如果不想指定子路径来传递参数,也可以通过 ?= 的形式来传递参数,例如:/article?id=xxx,这种情况下,可以通过request.args.get('id')来获取id的值。如果是post方法,则可以通过request.form.get('id')来进行获取。 在flask中添加这类的地址参数需要先从flask中导入request,示例如下:

from flask import Flask
from flask import request


app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/corley')
def hello_corley():
    return '这是我的第一个Flask页面'

@app.route('/list/<int:aid>')
def article_list(aid):
    return '这是第{}篇文章'.format(aid)

@app.route('/list/<path:aid>')
def comment_list(aid):
    return '这是第{}个评论'.format(aid)

@app.route('/<any(notice,follow):url_path>/')
def message(url_path):
    return url_path

@app.route('/wd')
def baidu_search():
    return request.args.get('keyword')

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

显示:

flask url view map params wd
flask url view map params wd

显然,如果request.args.get()中传入的参数未在URL中传入,会报错,因为URL未传入keyword参数,所以request.args.get()方法的值为空,即视图函数baidu_search()返回的值为空,不能渲染,所以会报错。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-04-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Flask简介与URL和视图介绍
  • 一、虚拟环境介绍
    • 1.虚拟环境与全局环境
      • 2.为什么需要虚拟环境
        • 3.虚拟环境的安装和简单操作
          • pipenv的安装
          • 创建虚拟环境
          • pipfile和pipfile.lock
      • 二、Flask介绍
        • 1.Flask简介
          • 2.第一个Flask程序
          • 三、设置Debug模式
          • 四、配置与配置文件
            • 1.直接硬编码
              • 2.通过update()方法
                • 3.通过from_object()方法
                  • 4.通过from_pyfile()方法
                  • 五、URL与函数的映射
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档