对Flask感兴趣的,可以看下这个视频教程:http://study.163.com/course/courseLearn.htm?courseId=1004091002

1. 第一个 flask 程序

# 从 flask 框架中导入 flask 类
from flask import Flask # 用 flask() 初始化一个 flask 对象,并赋给 app
# 需传递一个参数 __name__
# 1. 方便 flask 框架去寻找资源
# 2. 方便 flask 插件去定位问题
app = Flask(__name__) # @app.route() 是一个装饰器,作用是对 url 与 视图函数进行映射
# 将 `/` 映射到 hello_world() 函数上
# 即用户访问 http://example:80/ 的时候,用 hello_world() 函数来响应
@app.route('/')
def hello_world():
return 'Hello World!' # 如果当前文件作为程序入口,那么就执行 app.run()
if __name__ == '__main__':
# app.run() 是启动一个应用服务器来响应用户请求并不断监听
# app.run() 是 FLask 中的一个测试应用服务器(性能差,在部署的时候应该使用 uwsgi 而不是 app.run)
# app.run() 在底层实际上是一个 while(True) 循环,循环体是 listen() 函数,不断地监听指定端口号
app.run(debug=True,port=8000)

2. 使用 Debug 模式

使用 Debug 模式有很多好处:

1. 将报错信息显示到浏览器上,而不需要进入编辑器中查看报错信息,方便开发者查看错误
2. 当检测到程序代码(.py文件)发生改动,程序会自动加载而不需要手动重启服务器

对 flask 程序使用 debug 模式有 4 种方式,如下:

2.1 在 app.run() 中使用

app.run() 中直接传入一个关键字参数:app.run(debug=True)

2.2 在主 app 文件中使用 app.debug=True

from flask import Flask
app = Flask(__name__)
app.debug = True # 在主 app 文件中使用
…… 略 ……

2.3 在主 app 文件中使用 app.config.update(DEBUG=True)

from flask import Flask
app = Flask(__name__)
app.config.update(DEBUG=True) # 在主 app 文件中使用
…… 略 ……

使用 app.config.update(DEBUG=True) 这种方法实际上是借助了 Python 中的字典(Dict)属性,即:

a = {'a':1}
b = {'b':2}
a.update(b)
print(a) # {'a':1,'b':2}
a.update(c=3)
print(a) # {'a':1,'b':2,'c':3}

可以使用 print(isinstance(app.config,dict)) 来判断 app.config 是不是一个字典类型的数据。但是要注意 DEBUG 一定要大写。

以上这三种开启 Debug 模式的方法比较简单,还有一种开启 Debug 模式的方法需要借助配置文件,借助配置文件开启 Debug 模式的方法也比较规范,如下。

2.4 在配置文件中使用

  1. 在相同目录下,新建一个 python 文件,建议命名为 config,并在里面指定该程序配置了 DEBUG 模式,即 config.py 文件的内容如下:

     config.py
    
     # encoding:utf-8
    DEBUG = True
    # SECRET_KEY
    # SQLALCHEMY_DB # 数据库的一些参数配置
  2. 然后在主 app 文件中导入这个文件并配置到 app 中,主 app 文件内容如下:

     First_Flask.py
    
     # encoding:utf-8
    from flask import Flask
    import config # 导入 config 配置文件 app = Flask(__name__)
    app.config.from_object(config) # 将该配置文件的配置信息应用到 app 中 @app.route('/')
    def hello_world():
    a = 3
    b = 0
    c = a/b
    return 'Hello,World.' if __name__ == '__main__':
    app.run()

2.5 PIN 码

开启了 DEBUG 模式后,当程序抛出异常,则可以在网页上对程序进行调试,在网页上报出的任何一行错误信息中都有一个命令行小图标,点击该图标就可以进行调试了。

但是要注意,如果想要在网页上对程序进行调试,那么就需要输入 PIN 码,PIN 码在 Pycharm 中执行程序的时候会显示,复制过去粘贴即可。其中,PIN 码的有效时间是 8 小时,保存在浏览器的 Cookie 中,所以也不用每次抛出异常时都要输入一遍 PIN 码。

PIN 码的作用是为了保证程序更加安全,比如我不想让其他开发者知道我的代码写的是什么,但是实际上并没有什么卵用,因为都是开发者,没必要隐藏自己的代码。这个机制反而更加麻烦了一些。

3. 应用配置文件的两种方式

  1. 如上所示,在主 app 文件中导入 config 文件后,使用 app.config.from_object(config) 来将配置文件应用到 app 中,如下所示:

     from flask import Flask
    import config
    app = Flask(__name__)
    app.config.from_object(config)
  2. 不需要 import config,直接使用 app.config.from_pyfile 来将配置文件应用到 app 中,如下所示:

     from flask import Flask
    app = Flask(__name__)
    app.config.from_pyfile('config.py')

    实际上,from_pyfile 并不局限于 python 文件,也可以是其他类型的文件,如 config.txt

    from_pyfile 还有一个被隐藏的默认参数是 silent=False,所以完整格式是 app.config.from_pyfile('config.py',silent=False)。当 silent 被置为 False 时,如果前面输入的文件不存在,则抛出异常;当 silent 被置为 True 时,则会忽略这种错误。

4. URL 传参到视图

参数的作用:可以在相同的 URL 但是指定不同的参数时,来加载不同的数据。

如:http://localhost:8000/article/abchttp://localhost:8000/article/def 中,两条 URL 的参数不同,我们可以获取这个参数并渲染后返回客户浏览器

如何传参:如何在 flask 中使用参数?有两种方式实现。

  1. 第一种,使用 path 的形式,将参数嵌入到路径中

    传递参数的语法是:/<参数名>/,在对应的视图函数中也要定义相同的参数名。如下代码所示:

     @app.route('/article/<id>')
    def article(id):
    return u'<h1>你请求的参数是:%s<h1>' % id

    如果要限制传入参数的数据类型,可以这么定义:/article/<数据类型:参数名>,如 /<int:id>/,如下:

     @app.route('/article/<int:id>')
    def article(id):
    return u'<h1>你请求的参数是:%s<h1>' % id

    对于这段代码,当浏览器中的 url 是 127.0.0.1:5000/article/1 时能正确返回,当 url 是 127.0.0.1:5000/article/abc 时则提示 not found。如果没有指定数据类型,则默认是 str 型。

    其中,这些类型可以是:

     string	默认的数据类型,接受没有斜杠"/"和"\"的任何字符
    int 只接受整型
    float 只接受浮点型
    path 与 string 类似,但是接受斜杠
    uuid 只接受 uuid 字符串,其中 uuid 是全球唯一的字符串,一般可以用来作为表的主键
    any 可以指定多种路径,示例说明:
    any 示例:
    @app.route('/<any(article,user):url_path>/<id>')
    def detail(url_path,id):
    return '详情页面,id=%s' % id
    # 这个方法用于不同的 url 对应相同的视图函数的需求
    # 例如:/article/1 和 /user/1 对应同一个视图函数
  2. 第二种,使用查询的方式,调用 request.args.get('args') 方法,获取问号传递的参数

     from flask import request
    …… 略 ……
    @app.route('/keyword/')
    def keyword_args():
    wd = request.args.get('wd')
    return '?后面的参数是:%s' % wd

    这样,就可以获取 url 后面以问号的形式跟上的关键字了,如:/keyword/?wd=python。如果需要传递多个参数,那么问号后面可以跟 & 符号进行连接,如:/keyword/wd=python&name=myyd

    那么在视图函数中再加上 name = request.args.get('name') 即可。

5. URL 反转

正转指的是:在获取到用户输入的 URL 后将该 URL 映射到对应的视图函数中,让对应的视图函数去处理该用户的请求;

反转指的是:与正转相反,通过视图函数来查找对应的 URL。

反转的作用是:1. 在页面重定向的时候会使用 URL 反转;2. 在模板中会使用 URL 反转

实现反转的方法:

  1. 在 flask 框架中导入 url_for 模块

  2. url_for('FunctionName',key=value) 实现反转

    第一个参数 FunctionName 是视图函数的函数名。

    第二个参数 key=value 是传递给视图函数的参数,即 @app.route('/article/<id>') 中的 id。如果这个参数在 @app.route() 时已被定义,则该参数则以 path 的形式出现在 url 中;如果这个参数在 @app.route() 时未被定义,则该参数通过问号 ? 跟在 url 的后面传递给后台。

    例如:

     @app.route('/article/<id>')
    def article(id):
    return 'article' print(url_for('article',id='123',name='myyd')) # /article/123?name=myyd
  3. 源代码如下

     from flask import Flask,url_for
    import config app = Flask(__name__)
    app.config.from_object(config) @app.route('/')
    def hello_world():
    print(url_for('article',id='123')) # /article/123
    print(url_for('article',id='123',name='myyd')) # /article/123?name=myyd
    print url_for('my_list') # /list/
    return 'Hello,World.' @app.route('/article/<id>/')
    def article(id):
    return u'<h1>你请求的参数是:%s<h1>' % id @app.route('/list/')
    def my_list():
    return '<h1>list</h1>' if __name__ == '__main__':
    app.run()

为什么需要 url_for ?

  1. 将来如果修改了 URL,但是没有修改 URL 对应的函数名,就不用到处去替换 URL 了。

  2. url_for 会自动地处理 URL 中的特殊字符(如"/"),不需要手动处理。

    如:print(url_for('article',next='/')) 会输出 /article/%2F,因为 "/" 在 URL 中有歧义。

6. 自定义 URL 转换器

客户提出两个需求

6.1 需求一:

在一个 URL 中,含有手机号码的变量,必须限定这个变量的字符串格式满足手机号码的格式。

为了实现这个需求,需要做如下几个步骤:

  1. 从 werkzeug.routing 导入 BaseConverter:from werzeug.routing import BaseConverter

  2. 实现一个类,继承自 BaseConverter,重写正则表达式

    查看 BaseConverter 中的底层定义:光标停留在 BaseConverter 上,按 Ctrl+B 组合键进入 BaseConverter 的定义代码,参考 PathConverter() 类的定义,依葫芦画瓢自定义一个手机号码格式的转换器。

     # PathConverter(葫芦)
    class PathConverter(BaseConverter):
    regex = '[^/].*?' # TelephoneConverter(瓢)
    class TelephoneConverter(BaseConverter):
    regex = '1[34578]\d{9}' # \d 代表数字,{9} 代表重复 9 次
  3. 添加自定义转换器到默认转换字典

    Flask 中原来就定义的转换器有:string、int、float、path、uuid、any 等,如下所示:

     DEFAULT_CONVERTERS = {
    'default': UnicodeConverter,
    'string': UnicodeConverter,
    'any': AnyConverter,
    'path': PathConverter,
    'int': IntegerConverter,
    'float': FloatConverter,
    'uuid': UUIDConverter,
    }

    所以我们需要将自定义的转换器也添加进来,有两种方式:第一种就是按照格式在 DEFAULT_CONVERTERS 中添加;第二种方式是借助 url_map 来实现,如下:

     app.url_map.converters['tel'] = TelephoneConverter
  4. 限制视图函数中的参数类型

     @app.route('/telephone/<tel:number>')	# 限制类型
    def telephone(number):
    return 'Number is %s' % number

6.2 需求二:

在一个 URL 中,包含 a+b 的 path,需要将其拆分为 ab,后台再进行处理。

传统方法如下:

在视图函数中对传进来的参数进行拆分:

@app.route('/list/<id>')
def my_list(id):
id_list = id.split('+')
return 'the id list is %s' % id_list
# 若浏览器地址栏的 url 写的是:127.0.0.1:5000/list/a+b
# 则返回页面的信息是:the id list is ['a','b'],而不是:the id list is a+b

对于传进来的参数,在调用视图函数时都要进行一次拆分,会降低执行效率,能否在传到视图函数之前就已经对 a+b 格式的参数进行拆分?

借助 URL 转换器:

在 URL 转换器中定义了一个两个函数:to_python()to_url()

  1. 前者的作用是:将 URL 中的参数经过解析后传递给视图函数,即在 to_python 函数体中解析 URL 中的参数,然后 return 到视图函数中作为参数,如下:

     class ListConverter(BaseConverter):
    def to_python(self,value): # value 就是 /list/ 后面本来要跟的 a+b
    return 'value.split('+')' # 然后以 ['a','b'] 的格式返回给视图函数 my_list()

    然后要记得添加到默认的转换器字典中:app.url_map.converters('List') = ListConverter,最后限制类型:@app.route('/list/<List:id>')

    这样,视图函数就不用再进行拆分处理,而是能直接拿到最终想要的内容。

  2. 后者的作用是:在使用 url_for 时将参数还原成 url,如下:

     class ListConverter(BaseConverter):
    def to_url(self,value): # value 就是从视图函数中传过来的参数 ['a','b']
    return "+".join(value) # 然后以 a+b 的格式返回给 url_for 的参数 @app.route('/')
    def index():
    return url_for('my_list',id=['a','b'])

注意:这两个函数是成对出现的,一般情况下,要解析也要还原。

源代码如下

from flask import Flask,url_for
from werkzeug.routing import BaseConverter class ListConverter(BaseConverter):
def to_python(self, value):
return value.split('+')
def to_url(self, value):
return "+".join(value) app = Flask(__name__)
app.url_map.converters['List'] = ListConverter @app.route('/')
def hello_world():
return url_for('my_list',id=['a','b']) @app.route('/list/<List:id>/')
def my_list(id):
return 'The List is %s' % id if __name__ == '__main__':
app.run(debug=True)

7. Flask 开发的小细节

  1. 想要让自己写的网站,在局域网中被其他网络设备访问,则必须指定 host,即 app.run(host='0.0.0.0'),同时还需要注意以下 3 点:

  2. 指定端口号:Flask 的默认端口号是 5000,如果想要改成 8000 端口,应将 app.run 写成 app.run(port=8000)

  3. URL 唯一

    在定义 URL 的时候,一定要记得在最后加一个 /,这是为了更好的用户体验。而且搜索引擎会将加了斜杠的和不加斜杠的 URL 视为两个不同的 URL,但实际上加不加斜杠都是同一个 URL,这样就会给搜索引擎造成一个误解。

  4. 指明 GET 或者 POST 请求

    参考我的另一片博客:Flask基础,第 10 点:GET 、POST 和 钩子函数。

8. 页面跳转和重定向

重定向指的是浏览器自动地从一个页面跳转到另一个页面,可以用在一些需求上,如:用户访问某些需要登录的页面时,如果用户没登录,则可以让他重定向到登录页面。重定向分为两种:永久性重定向和暂时性重定向。

8.1 永久性重定向

状态码是 301,多用于旧网址被废弃了要转到一个新网址上,如京东网站,当你访问 www.jingdong.com 时会被重定向到 www.jd.com,因为旧网址已经被弃用了,所以这种情况应该使用永久重定向。

8.2 暂时性重定向

状态码是 302,表示页面的暂时性跳转。比如访问一个需要权限的网页,如果当前用户没有登录,应该重定向到登录页面。这种情况下应该使用暂时性重定向。

8.3 重定向的实现

在 Flask 中,重定向是通过 flask.redirect(location,code=302) 这个函数来实现的。其中:locate 代表重定向之后的 URL,应该配合之前将的 url_for() 来使用,code 表示使用的状态码,默认是 302。

看一个具体的例子:

from flask import Flask,redirect,url_for,request

app = Flask(__name__)
app.debug = True @app.route('/')
def index():
return 'hello world' @app.route('/login/')
def login():
return '请登录!' @app.route('/profile/')
def profile():
name = request.args.get('name')
if name:
return '个人详情页面'
else:
return redirect(url_for('login')) if __name__ == '__main__':
app.run(host='0.0.0.0')

9. 视图函数 response 返回值详解

Flask 的视图函数默认只可以返回字符串、元组合 Response 对象,Flask 转换响应对象的逻辑是:

  1. 如果返回的是一个合法的相应对象,则直接返回;

  2. 如果返回的是一个字符串:

    则 Flask 会构建一个 werkzeug.wrappers.response 对象,response 对象会将该字符串作为主体,状态码为 200,MIME 类型为 text/html,即构建成为:response('string',status=200,mimetype='text/html') 然后返回 response 对象。我们在视图函数中使用 return 返回内容,实际上就是 Flask 帮我们完成的这个动作。

    所以视图函数中的 return 'Hello World!' 等价于 return response('Hello World!')

  3. 如果返回的是一个元组:

    元组的数据类型是(response,status,headers),其中,status 会覆盖默认的 200 状态码,header 可以是一个列表或者字典,作为额外的消息头。

  4. 如果非以上内容:

    Flask 会去底层调用 Response.force_type(rv,request,environ) 返回一个 response 对象。这样,视图函数在调用 return 的时候就可以正确返回了。如下例:

     from flask import Flask,Response,jsonify
    
     app = Flask(__name__)
    app.debug = True class JSONResponse(Response): @classmethod
    def force_type(cls, response, environ=None):
    '''
    这个方法只有在视图函数返回非字符串、非元组、非response对象的时候被调用
    response:视图函数的返回值
    '''
    print(response)
    print(type(response))
    # jsonify:除了将字典转换成json对象,还将该对象包装成了一个Response对象
    if isinstance(response,dict):
    return super(JSONResponse,cls).force_type(response,environ) app.response_class = JSONResponse @app.route('/dict/')
    def dict():
    return {'username':'myyd','age':18} if __name__ == '__main__':
    app.run(host='0.0.0.0')

    实现响应自定义内容,需要完成 3 个步骤:

    1. 继承自 Response
    2. 实现方法 force_type(cls,response,environ=None)
    3. 指定 app.response_class 为你自定义的 Response 对象

Flask-论坛开发-1-基础知识的更多相关文章

  1. ArcGIS API for JavaScript开发初探——基础知识

    1.前言 在ArcGIS Web API开发体系中一共有四大类,分别为: ArcGIS API for Flex ArcGIS API for JavaScript ArcGIS API for RE ...

  2. Java开发培训基础知识解析之反射机制

    Java是老牌编程语言,是当前应用最广泛的编程语言之一.想要学习Java你就一定要掌握Java基础知识,而反射对于初学Java的人来说绝对是非常重要的知识点.什么是反射?如何理解反射机制?如何使用反射 ...

  3. 【千纸诗书】—— PHP/MySQL二手书网站后台开发之基础知识

    前言: 在具体回顾每一个功能的实现前,还是有必要先温习一些项目涉及到的PHP.MySQL[语法基础].项目github地址:https://github.com/66Web/php_book_stor ...

  4. ArcGIS Engine开发前基础知识(4)

    ArcGIS不同开发方式的比较 关于GIS应用软件的开发,通常有三种方式:C/S架构.网络GIS和移动GIS.ArcGIS平台提供了对三种开发方式的支持,对于采用从C/S架构的大多数开发者来讲,首先想 ...

  5. ArcGIS Engine开发前基础知识(3)

    对象模型图 一.对象模型图中的类与接口 ArcGIS Engine 提供大量的对象,这些对象之间存在各种各样的关系,如继承.组合.关联等.对象模型图(Object model diagram,ODM) ...

  6. ArcGIS Engine开发前基础知识(1)

    ArcGIS二次开发是当前gis领域的一项重要必不可少的技能.下面介绍它的基本功能 一.ArcGIS Engine功能 在使用之前首先安装和部署arcgis sdk,(在这里不在赘述相关知识)可以实现 ...

  7. Python开发——1.基础知识

    一.开发 开发语言分为高级语言和低级语言 高级语言:Python.Java.PHP.C++.C#.GO.Ruby等:低级语言:C.汇编语言. 高级语言对应的是字节码,是将代码编译成字节码,然后交给机器 ...

  8. android开发学习---基础知识学习、如何导入已有项目和开发一个电话拨号器

    一.基础知识点学习  1.Android体系结构 如图所示,android 架构分为三层: (1)最底层是linux内核,主要是各种硬件的驱动,如相机驱动(Camera Driver),闪存驱动(Fl ...

  9. Unity游戏开发面试基础知识

    面试第一次知识总结: 一.Unity基本操作 1.unity提供哪几种光源? 点光源.平行光.聚光灯.区域光. 2.物体发生碰撞的必要条件什么? 两个物体必须有碰撞体Collider组件,一个物体上必 ...

  10. ArcGIS Engine开发前基础知识(2)

    ArcGIS基本控件简介 ArcGIS Engine控件是一组可视化的开发组件,每个ArcGIS Engine控件都是一个COM组件.这些组件包括MapControl,PageLayoutContro ...

随机推荐

  1. Nginx使用教程(一):下载并编译安装Nginx

    安装依赖 <br\>我们已经选择下载程序源代码进行手动编译,而不是使用软件包管理器(如Yum,Aptitude或Yast)进行安装. 这个选择有两个原因. 首先,软件包可能不包含在您的Li ...

  2. MySQL主从同步原理

    mysql主从复制用途 实时灾备,用于故障切换 读写分离,提供查询服务 备份,避免影响业务 主从部署必要条件 主库开启binlo日志(设置log-bin参数) 主从server-id不同 从库可以连同 ...

  3. 遗传算法MATLAB工具包简介

    下面介绍的函数都是Sheriffed大学遗传算法工具包内的常用函数 复制矩阵 B=rep(A,RepN) 1 A表示要被复制的矩阵,RepN包含每个方向的复制次数,RepN(1)代表纵向复制次数,Re ...

  4. 使用Nginx来解决跨域的问题

    使用Nginx来解决跨域的问题 nginx的版本:(查看nginx命令: /usr/local/nginx/sbin/nginx -v) nginx/1.4.3 问题是:前端项目域名是 a.xxxx. ...

  5. WebSocket原理与实践(四)--生成数据帧

    WebSocket原理与实践(四)--生成数据帧 从服务器发往客户端的数据也是同样的数据帧,但是从服务器发送到客户端的数据帧不需要掩码的.我们自己需要去生成数据帧,解析数据帧的时候我们需要分片. 消息 ...

  6. Selenium:HTML测试报告

    自动化测试过程中,获得用例的执行结果后,需要有具象化.简洁明了的测试结果,比如:用例执行时间.失败用例数.失败的原因等,这时候,就需要用到测试报告. HTML测试报告是python语言自带的单元测试框 ...

  7. CMD命令查看当前电脑安装所有版本.NET Core SDK(转载)

    dotnet --version 查看当前使用版本 dotnet --info 安装的所有版本 包括版本地址 也可用命令帮助 dotnet help 原文链接

  8. 如何在Virtual box 下安装Mac os

    这几天,突然奇想,想要试一试Mac  os ,毕竟是贵族系统,装完之后,确实感觉字体很不错. 其他更优秀的功能还没发现,不过,还是希望在这里做一个记录. 以下附录我参照的网址:https://blog ...

  9. Flask核心机制--上下文源码剖析

    一.前言 了解过flask的python开发者想必都知道flask中核心机制莫过于上下文管理,当然学习flask如果不了解其中的处理流程,可能在很多问题上不能得到解决,当然我在写本篇文章之前也看到了很 ...

  10. odoo 11导入外部数据过程记录

    在开发过程中,遇见需要将SQL Server中的数据转移到Pg数据库的情况,那么如何做才能解决这一问题呢? 1.自己写代码,将数据从SQL Server到PG. 2.利用odoo自带的导入功能导入. ...