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

从示例代码说起:

 from flask import Flask
app = Flask(__name__) @app.route('/')
def hello_world():
return 'Hello, World!'

第1行从flask模块导入Flask类;

第2行定义一个Flask实例,每一个Flask实例都是一个WSGI应用(Application);

参数是否为__name__是由模块是否 作为应用启动 还是 作为模块导入。在示例中,只有一个模块,并且是作为应用启动,因此,参数为__name__。

在Flask的介绍文档中,Flask(...)函数是有多个参数的,这些参数用于指定应用怎么寻找模板、静态文件等。

通常来讲,用户需要在 主模块或__init__.py文件 中创建Flask实例。

第4行使用route函数告知Flask在接收到URL位“/”时交由hello_world函数处理;

说明,截止此时, 我仍然不清楚如何创建更复杂的Flask应用——包含静态文件、模板文件、配置文件等的应用。

在将示例程序改造为包形式时出现了下面的问题:

1.文件夹下新建了__init__.py,并将Flask实例的创建代码放入其中;

 from flask import Flask

 app = Flask('HelloWorld')

2.改造后的hello.py

 @app.route("/")
def hello():
return "Hello World!"

3.运行应用

跳转到HelloWorld的上一级目录Flask,下图为执行情况:Flask应用启动成功

4.访问页面

发生错误,没有显示hello.py模块中输出的Hello World!,如下图:

后面又做了一下尝试,在__init__.py中添加了下面这句:

from HelloWorld import hello

结果,服务器运行不起来了,提示:

File "C:\Python36\ws\Flask\HelloWorld\hello.py", line 1, in <module>
@app.route("/")
NameError: name 'app' is not defined

app是在__init__.py中定义的,而hello.py模块并没有权限获取它吧?

然后给__init__.py的app前加一个global关键字,结果,提示语法错误!

app的定义要和其它URL的route调用放在同一个模块文件中?

……

接下来,怎么办?(一筹莫展也和自己的Python基础有关系吧)

----

在运行Flask项目时发现一个陷阱:Windows下SET命令设置环境变量时,等号前后不能有空格。

下图是有空格的,启动Flask项目失败:

下图么有空格,启动Flask项目成功:

----

启动Flask项目的两种方式

1.使用python -m flask run命令

2.使用flask run命令(Python的Scripts添加到Windows的Path环境变量后可用)

flask run还有更多参数可用,可以查看其帮助信息(flask run --help):

补充说明:

1.Flask项目如上面一样启动后,只能在本机访问;怎么让Flask项目可以被同网络的其它主机访问呢?使用-h/--host配置项绑定网卡地址;

疑问:不知道是否支持IPv6地址。

2.使用-h/--host配置项时,可以将参数设置为0.0.0.0,表示从本机的任何网卡都可以访问,如果固定到某一个IP地址,则只是绑定了那个IP地址所在

网卡,此时只有那个IP所在网络的主机可以访问;

在设置了-h/--host配置项启动时,Windows弹出了报警窗口:

3.Flask项目的默认端口是5000,使用-p/--port来指定;

还要检查所配置的端口是否被防火墙等软件屏蔽了,若是,需要开启。

还有其它配置项,还需更多了解。

----

开启调试模式,只需要在Flask项目启动时设置环境变量FLASK_ENV为development即可。

当然,前面所述,也可以在启动时使用--debugger配置项打开。

注意,一定要在生产环境中把调试器关闭!否则会有很大的安全隐患!

使用调试器的更多信息,还需要学习实践。

--

Routing

可以翻译为 URL路由,即定义Flask如何将各个URL请求进行转发,转发到函数,或者其它地方(哪里?尚不清楚)。

route()函数用于将某个函数绑定到URL。

示例:

@app.route('/')

@app.route('/hello')

上面两个都是静态的URL,开发人员可以将URL变为动态的并绑定多个规则到一个函数(N URLs TO a FUNCTION)。

Quickstart中介绍了下面几种:

1.变量规则(Variable Rules)

在URL中添加变量部分:<变量名>

函数会将收到的<变量名>作为关键词参数。

还可以选择用转换器指定参数的类型:<转换器:变量名>

转换器类型有5种:string, int, float, path, uuid (UUID string,见uuid模块)

示例:

@app.route('/user/<username>')

@app.route('/post/<int:post_id>')

@app.route('/path/<path:subpath>')

2.唯一URL/重定向(Unique URLs / Redirection Behavior)

说明,这一小节没看懂。

Quickstart中举了下面两个例子:

@app.route('/projects/')

@app.route('/about')

其中,第一个以斜杠结束,第二个没有斜杠。

在访问第一个时,如果你没有加斜杠,那么,Flask会自动帮你跳转并添加;

而在访问第二个时,如果加了斜线,那么抱歉,404等着你。

好处是什么呢?

帮助保证这些资源的URL唯一性,而这又可以帮助避免搜索引擎把相同的页面做两次索引。

好吧,还是不太明白,但会是个好东西的。

3.URL构建(URL Building)

用处:给指定函数构建一个URL,使用url_for()函数。

此函数接收的第一个参数为函数名,而其它有一些数量的参数被当作关键词参数,每一个都对应着URL规则的变量部分。

还有一些不知道的变量部分被附加到URL后作为查询参数。

为何要这么做呢?而不是如前面讲的硬编码到函数模板中?

a.反转经常比硬编码有更多描述性东西;

b.开发者可以一口气改变URL,而不需要记得去手动更改硬编码的URL;

c.URL构建可以透明地处理特殊字符和Unicode字符的转义(escaping);

d.产生的路径总是绝对路径,这避免了在浏览器中使用相对路径可能发生的一些非预期错误;

e.如果你的应用放在了URL根目录之外,url_for()也可以正确的处理;(不明白,需要例子)

Quickstart中举了一个例子,感觉它就是把几个url_for()函数转换的结果打印出来了,可是,对于项目的请求、响应有什么用呢?

难道客户端只能使用url_for()转换的URL去访问?比如,那么,代码中的硬编码的例子还有效吗?

4.HTTP方法

route()函数的参数包括一个名为methods的,可以用来限制访问URL的请求方法(常见的请求访问有GET、POST,还有其它的)。

示例:

@app.route('/login', methods=['GET', 'POST'])

上面的示例近允许了GET、POST方法的请求访问,其它的就不可以了。

另外,GET方法允许后,HEAD方法自动就允许了。

--

静态文件(Static Files)

在生产环境,HTTP服务器可以处理静态文件;但在开发过程中,Flask也可以处理静态文件。

在package下建立一个名为static的文件夹,或者,和你的模块文件在同一级目录,然后,静态文件就可以以"/static"开头的URL进行访问了。

--

渲染模板(Rendering Templates)

Flask自动配置了Jinja2模板引擎。可以使用render_template()函数渲染一个模板。开发者唯一要做的是,传递模板文件名和关键词参数给render_template()函数。

示例:

 from flask import render_template

 @app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)

Flask会在templats文件夹中寻找模板文件,此文件夹和前面的static文件夹的位置相同,同级。

模板怎么写?常见的HTML、JavaScript、CSS外, 就是模板相关的变量、标签、流程控制、过滤器、模板继承、自动转义等,在Jinja2中还发现一个新的Markup类。

更多关于模板的内容,还是要看看Jinja2的文档

--

访问请求数据(Accessing Request Data)

Flask中提供了 全局的request对象 用来保存客户端请求的数据。

为什么这个对象是全局的?Flask又是怎么做到线程安全的?哈,不懂,更不懂为何要提出这样的问题,好尴尬。

因为Flask有一个 本地化上下文功能(Context Locals)。

此小节包含四部分:

1.本地化上下文(下面主要是翻译Quickstart中的内容)

Flask中的一些对象是全局的,这些对象实际上是 代理,代理的是本地的到一些具体的上下文的对象。

把这些上下文想象成处理中的线程。一个请求近来,Flask决定新建一个线程。在Flask开始内部请求处理时,它清楚当前线程是 活跃的(active),并且

绑定到当前的应用和WSGI环境。

Flask再次用了一种智能的方法,因此,一个应用可以 不用中断 就发起(invoke)另一个应用。

这对开发者有什么用啊?基本上是可以忽略的,除非要做单元测试类的工作。你会注意到,那些依赖于request对象的代码可能突然 因为没有request对象 而被打断。

解决办法就是,创建你自己的 并 绑定到上下文中。

Quickstart中还有两个关于 解决方案 的例子,大家可以去看看。

1041.说实话,暂时没看明白这个。

2.Request对象

导入请求对象:

from flask import request

当前可用请求方法 通过method属性:

if request.method == 'POST':

访问表单数据可以使用form属性:

request.form['username']

request.form['password']

说明,表单数据如果不在form属性中怎么办?KeyError!可以抓取到它并处理,或者,返回一个400页面。

访问URL中提交的参数(?key=value)使用args属性:

searchwords = request.args.get('key', '')

Flask推荐使用get方法获取,因为其已经对KeyError进行了处理,否则发生错误时返回不有好的400页面。

更多关于request的内容,需要查看requst的文档

3.文件上传

使用Flask处理文件上传很容易。

上传的文件被保存到 内存 或 文件系统中的某个临时位置。

开发者可以通过reqest对象的files属性查看这些上传的文件。

这些文件表现的就像是Python文件对象,当仍然有一个save()方法可以让开发者可以将它们保存到服务器的文件系统中。

例子:

 from flask import request

 @app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/uploaded_file.txt')

想要知道文件在客户端的名字?可以使用filename属性。但是千万注意,这个filename属性可能会被伪造,若是你需要使用这个属性,请将它

传递给werkzeug模块的secure_filename()方法再用。

例子:

from flask import request
from werkzeug.utils import secure_filename @app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/' + secure_filename(f.filename))
...

更多关于文件上传的内容,可以查看Flask的文件上传模式文档

4.Cookies

可以使用cookies属性访问cookies。

可以使用response对象的set_cookie方法设置cookie。

注意,若是你要使用sessions,那么,请不要直接使用Cookies。因为Flask中的sessions是在cookies的上面添加了一些安全机制的。

例子:读取cookies

username = request.cookies.get('username')

例子:存储cookies

 from flask import make_response

 @app.route('/')
def index():
resp = make_response(render_template(...))
resp.set_cookie('username', 'the username')
return resp

注意上面的make_response()函数的用法:这个方法用于创建你自己的response对象,并可以使用新建对象给返回结果添加一些 头部信息,当然,也包括设置cookies了。

--

重定向和错误(Redirects and Errors)

将用户重定向到另外的终端页面(endpoint),可以使用redirect()函数:

return redirect(url_for('login'))

P.S.看到了url_for()函数函数的用法,好开心。

提前终止请求并返回一个错误码,可以使用abort()函数:此函数调用后的代码就 不会被执行了

abort(401)

定制错误页面 请使用errorhandler()装饰器:

 from flask import render_template

 @app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'), 404 # 不要忘记这里的404

--

关于响应(About Responses)

从一个视图函数返回的数据会被 自动转换成一个response对象。

Flask采用的逻辑如下:

a.如果response对象的类型正确,直接返回;

b.如果是字符串,使用这个数据和默认参数创建一个response对象;

c.如果是元组(tuple),元组的格式需要是(response, status, headers) 或者 (response, headers);P.S.这一段没翻译明白,也没弄太清楚

d.如果上面的都不是,Flask会假设返回的数据时一个有效的WSGI应用,并将之转换为一个response对象。

提示,如果开发者想要深入掌控response对象,可以使用make_response()方法。正如前面有提到——该header,用make_response()。

详见Quickstart中例子。

resp = make_response(render_template('error.html'), 404)

--

Sessions

和请求对象相关联的是一个叫做session的对象,这个对象用于记录 具体用户访问应用时的 一些信息(什么信息?)。

它是cookies上面实现的,并用加密的方式为cookies进行签名。这意味着,用户可以查看你的cookies的内容,但无法修改它,除非他们知道用于加密的密钥。

P.S.有什么用?签名后的cookies是怎么样的?看来,自己还是缺乏经验啊,

为了使用session,开发和需要设置应用的密钥(app.secret_key)(后文会讲怎么创建):

 # Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/' # 随机bytes

看来这里设置后,Flask的sessions就使用这个密码去给cookies前面了啊。

session的一些示例操作(下面的代码并非在一起的):

 return 'Logged in as %s' % escape(session['username'])
...
session['username'] = request.form['username']
...
# remove the username from the session if it's there
session.pop('username', None)

详见官网sessions文档

怎么产生好的密钥(Hot to generate good secret keys)

执行下面的命令:

python -c "import os; print(os.urandom(16))"

注意,用双引号,而不是单引号!Quickstart中的是错误的!

注意,使用python3得到的和Quickstart中得到的不一样,不清楚怎么转换!

如下图:Python3转换出来哦,好像还能看的懂,Python2的就……,看来要限制产生的字符的范围,比如,只能是数字、字母、标点符号等。

注意:关于 基于cookies的sessions,Flask会获取你存储到sessions中的数据,并将它们序列化到cookie中。如果你发现某些数据在跨请求时没有

找到,那么,在确认cookies在客户端使能了,也没有获得明显错误信息时,请检查页面响应中的cookies的长度和Web浏览器支持的长度。

除了默认的基于客户端的sessions外,开发者还可以使用Flask的一些扩展模块去支持 服务器端sessions。

问题:基于客户端sessions、基于服务器端sessions,两者的区别是什么?分别有什么用?TBD

--

Message flashing

Flask使用flashing系统 给用户提供了一个简单的获取反馈的方法。

flashing系统基本上实现了 在请求最后记录一个信息,并在下一个请求仅仅是下一个请求时读取它。

这通常是和layout template联合使用以暴露信息。

使用flash()函数flash一个消息,使用get_flashed_messages()函数获取所有消息。

还不是太明白,,更多信息见官方文档

--

Logging

浏览器访问不一定总是正确的,当错误、异常、恶意攻击等行为发生时,开发者应该记录相关问题。

这时,就可以使用Flask提供的logger了,从Flask 0.3版本就预配置好了。

Flask的logger是一个标准的日志记录器,可以到官网查看更多信息。

另外,关于应用可能发生的错误,请参考官网的应用错误文档

--

Hooking in WSGI中间件

如果开发者想添加一个WSGI中间件到应用中,可以采用包装内部的WSGI应用。

P.S.不明白有什么用

--

使用Flask扩展

查找更多Flask扩展程序,请访问官网Extensions文档

--

部署到一个Web服务器

请查看官方文档Deployment Options

--

后记:

总算写完了,昨天下午+昨天晚上一小时+今天10点开工到现在。

写完后,有什么进步吗?更牢靠了。可是,更熟练使用Flask了吗?

况且Quickstart文档中的不少内容都没整明白。

现在,要更进一步熟悉Flask需要:1.看更多文档、2.开发项目——在开发中学习。

还要多练习。

又是一篇长长的博文,也是醉了,感觉就是把Quickstart翻译了一遍,,至此,还有什么问题呢?

声明:

由于作者水平有限,如有错漏,请提醒通知。

Flask: Quickstart解读的更多相关文章

  1. flask安装及第一个程序

    1.flask是一个轻量级的python web框架 ·1.Flask 依赖两个外部库: Jinja2 模板引擎和 Werkzeug WSGI 套件 ·2.安装: # easy_install fla ...

  2. Flask服务入门案例

    安装 pip install Flask 入门例子 from flask import Flask app = Flask(__name__) @app.route('/hello.world') d ...

  3. PythonWEB框架之Flask

    前言: Django:1个重武器,包含了web开发中常用的功能.组件的框架:(ORM.Session.Form.Admin.分页.中间件.信号.缓存.ContenType....): Tornado: ...

  4. [转]python实现RESTful服务(基于flask)

    python实现RESTful服务(基于flask) 原文: https://www.jianshu.com/p/6ac1cab17929  前言 上一篇文章讲到如何用java实现RESTful服务, ...

  5. flask实现简单的接收json返回json的接口

    结合http://docs.jinkan.org/docs/flask/quickstart.html#a-minimal-application这个flask文档实现 #!/usr/bin/pyth ...

  6. Flask 学习资源

    http://docs.jinkan.org/docs/flask/quickstart.html

  7. Python Web开发之Flask

    PythonWEB框架之Flask 前言: Django:1个重武器,包含了web开发中常用的功能.组件的框架:(ORM.Session.Form.Admin.分页.中间件.信号.缓存.ContenT ...

  8. Flask 安装 快速入门

    $ pip install flask Flask自带的Server在端口5000上监听: ython app.py flask通过request.form['name']来获取表单的内容. 外部可见 ...

  9. 搭建 flask 应用

    参考文档:http://docs.jinkan.org/docs/flask/quickstart.html#a-minimal-application 1.使用Pycharm创建Flask应用 fr ...

随机推荐

  1. 一种KEIL中定义过的变量在使用中提示未定义的情况

    [环境] > KEIL5.25 > win10 > @2018-4-23 [问题] 头文件互包含导致的错误(使用了另一文件的类型定义) 文件<fileA.h> <f ...

  2. python模块之 paramiko

    paramiko模块提供了ssh及sft进行远程登录服务器执行命令和上传下载文件的功能.这是一个第三方的软件包,使用之前需要安装. 1 基于用户名和密码的 sshclient 方式登录 # 建立一个s ...

  3. npm publish gives “unscoped packages cannot be private”

    解决方法: npm publish --access public 详细参考此处

  4. 服务器(Linux) 安装python3

    1.python3和python2可以共存,不用删自带的python2 服务器Linux下默认系统自带python2.6的版本,这个版本被系统很多程序所依赖,所以不建议删除.如果使用最新的Python ...

  5. python基础之while语句continue以及break --语法以及案例

    1.while 死循环 [root@localhost python]# cat while.py #!/usr/bin/env python # _*_ coding:utf8 _*_ import ...

  6. 「Vue」Vue cli3中引用mui-ui问题及解决办法

    1.引用mui.js无效,top-bar划动,numbox点击无效等问题 解决办法: -main.js中import mui from './lib/mui/js/mui.js' Vue.protot ...

  7. socket利用多线程实现一对多通信

    1.服务器端:socket()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接.将accept()写入死循环,每次连接一个客户端,开一个线程. 2.一般情况下建立s ...

  8. [Web] Web请求过程之二:DNS 域名解析

    一.域名解析过程 1.浏览器检查缓存,域名缓存时间可以通过 TTL 属性来设置. 2.如果浏览器缓存中没有,浏览器会去查找操作系统缓存中是否有这个域名对应的 DNS 解析结果.如果要设置域名对应的 I ...

  9. linux服务器上修改oracle数据库的字符集

    linux服务器上以dba身份进入:sqlplus / as sysdba; 依次执行以下命令:shutdown immediate; startup mount; alter system enab ...

  10. 《Science》:对年轻科学家的忠告