flask内容
Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。
“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。
默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。
flask中虚拟环境的搭建(参考博客)
sudo pip install virtualenv
sudo pip install virtualenvwrapper # 1、创建目录用来存放虚拟环境
mkdir
$HOME/.virtualenvs # 2、打开~/.bashrc文件,并添加如下:
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh # 3、运行
source ~/.bashrc 创建虚拟环境
mkvirtualenv 虚拟环境名称
例 :
mkvirtualenv py_flask mkvirtualenv -p python3 虚拟环境名称
例 :
mkvirtualenv -p python3 py3_flask 进入虚拟环境
workon 虚拟环境名称 例 :使用python2的虚拟环境
workon py_flask 例 :使用python3的虚拟环境
workon py3_flask 退出虚拟环境
deactivate rmvirtualenv 虚拟环境名称 例 :删除虚拟环境py3_flask 先退出:deactivate
再删除:rmvirtualenv py3_flask 在虚拟环境中安装包
pip install 包名称
flask虚拟环境的搭建
一,flask的基本使用:
from flask import Flask app = Flask(__name__) @app.route('/')
def hello_world():
return 'Hello World!' if __name__ == '__main__':
app.run(debug=True)
flask的基本使用
二,基本的配置
# default_config = ImmutableDict({
# 'DEBUG': False,
# 'TESTING': False,
# 'PROPAGATE_EXCEPTIONS': None,
# 'PRESERVE_CONTEXT_ON_EXCEPTION': None,
# 'SECRET_KEY': None,
# 'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
# 'USE_X_SENDFILE': False,
# 'LOGGER_NAME': None,
# 'SERVER_NAME': None,
# 'APPLICATION_ROOT': None,
# 'SESSION_COOKIE_NAME': 'session',
# 'SESSION_COOKIE_DOMAIN': None,
# 'SESSION_COOKIE_PATH': None,
# 'SESSION_COOKIE_HTTPONLY': True,
# 'SESSION_COOKIE_SECURE': False,
# 'MAX_CONTENT_LENGTH': None,
# 'SEND_FILE_MAX_AGE_DEFAULT': 12 * 60 * 60, # 12 hours
# 'TRAP_BAD_REQUEST_ERRORS': False,
# 'TRAP_HTTP_EXCEPTIONS': False,
# 'PREFERRED_URL_SCHEME': 'http',
# 'JSON_AS_ASCII': True,
# 'JSON_SORT_KEYS': True,
# 'JSONIFY_PRETTYPRINT_REGULAR': True,
# }) 方式一
创建 Flask 类的对象,指向程序所在的包的名称
app = Flask(__name__) # 从配置文件中加载配置
app.config.from_pyfile('config.ini') 方式二:
# 配置对象,里面定义需要给 APP 添加的一系列配置
class Config(object):
# DEBUG = True # 创建 Flask 类的对象,指向程序所在的包的名称
app = Flask(__name__) # 从配置对象中加载配置
app.config.from_object(Config)
配置文件的方式
三,路由系统
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
路由关系的创建
from flask import Flask
from flask import request app = Flask(__name__) # 指定访问路径为 demo1
@app.route('/demo1')
def demo1():
return 'demo1' # 路由传递的参数默认当做 string 处理,也可以指定参数的类型
@app.route('/user/<int:user_id>')
def user_info(user_id):
return 'hello %d' % user_id @app.route('/demo2', methods=['GET', 'POST'])
def demo2():
# 直接从请求中取到请求方式并返回
return request.method if __name__ == '__main__':
app.run(debug=True)
from werkzeug.routing import BaseConverter
from flask import Flask # 自定义正则转换器
class RegexConverter(BaseConverter):
def __init__(self, url_map, *args):
super(RegexConverter, self).__init__(url_map)
# 将接受的第1个参数当作匹配规则进行保存
self.regex = args[0] app = Flask(__name__) # 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re
app.url_map.converters['re'] = RegexConverter @app.route('/user/<re("[0-9]{3}"):user_id>')
def user_info(user_id):
return "user_id 为 %s" % user_id if __name__ == '__main__':
app.run(debug=True)
自定义路由正则
from werkzeug.routing import BaseConverter
from flask import Flask # 自定义正则转换器
class RegexConverter(BaseConverter):
def __init__(self, url_map, *args):
super(RegexConverter, self).__init__(url_map)
# 将接受的第1个参数当作匹配规则进行保存
self.regex = args[0] def to_python(self, value):
return int(value) app = Flask(__name__) # 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re
app.url_map.converters['re'] = RegexConverter @app.route('/user/<re("[0-9]{3}"):user_id>')
def user_info(user_id):
print("user_id的类型为", type(user_id))
return "user_id 为 %s" % user_id if __name__ == '__main__':
app.run(debug=True)
to_python方法
to_url:
在使用 url_for 去获取视图函数所对应的 url 的时候,会调用此方法对 url_for 后面传入的视图函数参数做进一步处理
具体可参见 Flask 的 app.py 中写的示例代码:ListConverter
to_url方法
视图的常用逻辑
不推荐使用 json.dumps 转成 JSON 字符串直接返回,因为返回的数据要符合 HTTP 协议规范,
如果是 JSON 需要指定 content-type:application/json
from flask import Flask
from flask import jsonify app = Flask(__name__) # 返回JSON
@app.route('/demo4')
def demo4():
json_dict = {
"user_id": 10,
"user_name": "laowang"
}
return jsonify(json_dict) if __name__ == '__main__':
app.run(debug=True) # 不推荐使用 json.dumps 转成 JSON 字符串直接返回,因为返回的数据要符合 HTTP 协议规范,
# 如果是 JSON 需要指定 content-type:application/json
数据的返回
重定向
重定向到指定的网址
from flask import Flask
from flask import redirect app = Flask(__name__) @app.route('/demo5')
def demo5():
return redirect('http://www.itheima.com') if __name__ == '__main__':
app.run(debug=True)
重定向到自己写的函数中
@app.route('/demo1')
def demo1():
return 'demo1' @app.route('/demo5')
def demo5():
return redirect(url_for('demo1'))
重定向到带有参数的路由函数中
# 路由传递参数
@app.route('/user/<int:user_id>')
def user_info(user_id):
return 'hello %d' % user_id # 重定向
@app.route('/demo5')
def demo5():
# 使用 url_for 生成指定视图函数所对应的 url
return redirect(url_for('user_info', user_id=100))
自定义状态码
@app.route('/demo6')
def demo6():
return '状态码为 666', 666
异常的捕获
from flask import Flask
from flask import abort app = Flask(__name__) @app.route('/')
def hello_world():
return 'Hello World!' @app.route("/demo1")
def demo1():
# 主动http状态码
abort(404)
return "demo1" # 使用装饰器来捕获异常指定的状态码和异常
@app.errorhandler(404)
def page_not_fund(error):
print(error)
return "页面不存在" @app.route("/demo2")
def div_demo2():
a = 5
b = 0
return a / b # 使用错误捕获来捕获除数不能为0的的错误
@app.errorhandler(ZeroDivisionError)
def Zero_Division_Error(error):
print(error)
return "除数不能为0" # 第二种捕获异常的方式
# def page_not_found(error):
# return '你访问的页面不存在', 404
# app.error_handler_spec[None][404] = page_not_found if __name__ == '__main__':
app.run(debug=True)
注册一个处理程序错误的装饰器,当程序抛出指定错误状态码的时候会调用装饰器所装饰的方法(除了捕获异常的状态码之外还可以捕获指定的异常)
flask中的请求钩子
#! /usr/bin/env python
# *-* coding: utf-8 *-* from flask import Flask app = Flask(__name__) @app.before_first_request
def before_first_request():
print("before_first_request") @app.before_request
def before_request():
print("before_request") @app.after_request
def after_request(response):
print("response", response)
print("after_request")
return response # 在请求之后可以被执行,如果有异常会将此异常传入到这个函数来做处理
@app.teardown_request
def teardown_request(error):
print(error)
print("teardown_request") @app.route('/')
def index():
print("index", index)
return 'index' if __name__ == '__main__':
app.run(debug=True)
before_first_request(在处理第一个请求前执行,后续的执行过程就不会再执行了)
before_request(每次发起请求前都会执行,如果在某个修饰函数中返回一个响应,视图函数将不再被调用)
after_request
(
没有抛出异常,则在每次请求后会执行
接收一个参数:视图函数做出的响应;
在此函数中可以对视图函数做出的响应做最后一步的处理;
需要将参数中的响应在此函数中返回
)
teardown_request
(
每次请求之后都会执行;
接收一个参数:如果抛出异常,则参数会捕捉到这个异常;
)
#! /usr/bin/env python
# *-* coding: utf-8 *-* from flask import Flask,request
from werkzeug.serving import run_simple app = Flask(__name__) @app.route('/')
def hello_world():
return 'Hello World!' @app.route('/index', methods=["POST",])
def index():
print(request.method)
return 'index index!' # rule 视图函数和酷游关系的映射关系
# map rule的集合
# BaseConverter匹配路由匹配的规则
# MapAdapter协调以上的路由匹配的工作 if __name__ == '__main__':
print(app.url_map)
app.run(debug=True)
装饰器路由功能的实现
Werkzeug库的 routing 模块负责实现 URL 解析。不同的 URL 对应不同的视图函数,routing模块会对请求信息的URL进行解析,匹配到URL对应的视图函数,执行该函数以此生成一个响应信息。
routing模块内部有:
- Rule类
- 用来构造不同的URL模式的对象,路由URL规则
- Map类
- 存储所有的URL规则和一些配置参数
- BaseConverter的子类
- 负责定义匹配规则
- MapAdapter类
- 负责协调Rule做具体的匹配的工作
- Rule类
请求上下文(request context)
#! /usr/bin/env python
# *-* coding: utf-8 *-* from flask import Flask
from flask import request app = Flask(__name__) @app.route('/index', methods=["GET", "POST"])
def index():
return 'Hello World!' @app.route("/args", methods=["GET", "POST"])
def args():
# get方式地址栏传递参数
print(request.form.get("name"))
print(request.form.get("age"))
# post方式请求体中传递参数
print(request.args.get("name"))
print(request.args.get("age"))
return "success" @app.route("/file", methods=["POST"])
def up_load_file():
print(request.method)
pic = request.files.get("pic")
pic.save("./static/aaaa.png")
return "success" if __name__ == '__main__':
app.run(debug=True)
request的使用
request是flask中代表当前请求的request对象,是一个全局的请求上下文的一个变量(可以理解成为一个全局变量,在视图函数中可以直接使用,可以取到当前请求)。
备注:在地址栏中请求数据的方式可以用args的方式去在request中取值,如果在form表单中的数据需要在form中取值。
cookie的设置
#! /usr/bin/env python
# *-* coding: utf-8 *-* from flask import Flask
from flask import request
from flask import make_response app = Flask(__name__) # 获取cookies
@app.route('/index')
def index():
username = request.cookies.get("username")
user_id = request.cookies.get("user_id")
return '%s---%s' % (username, user_id) # 设置cookies
@app.route("/login")
def login():
response = make_response("success")
response.set_cookie("username", "xiaoimng", max_age=3600)
response.set_cookie("user_id", "", max_age=3600)
return response # 删除cookies
@app.route("/logout")
def logout(): response = make_response("删除cookies成功")
response.delete_cookie("user_id")
response.delete_cookie("username")
return response if __name__ == '__main__':
app.run(debug=True)
cookie的设置
备注:
1,cookie的设置是在response中进行设置,在request中取值;
2,http是一种无状态的协议,浏览器在请求服务器的时候是无状态的,
无状态的原因是:
浏览器与服务器通过socket进行通信,服务器会将请求结果返回给浏览器,请求完毕后服务器都会将通信套接字关闭,并且服务器在关闭套接字之后就会销毁请求的页面的对象;
有时需要保持浏览器的状态,比如用户的登录状态,和浏览过的信息等;
无状态协议
1,协议对事物的处理没有记忆的功能;
2,对于同一个url请求没有上下文的关系;
3,每次执行的结果都是独立的,它执行的结果和情况与上前面的请求和之后的请求没有直接的关系,它不会受前面的请求应答的影响,也不会对后面的请求应答产生影响;
4,服务器没有保持客户端的状态,客户端每次需要自己将状态带到服务区端;
实现状态保持有两种方式;
1,在客户端设置cookie,在每次发送请求的时候将cookie带给服务器端;
2,在服务器端设置session,每次客户福安发送来请求之后,将客户端的cookie与session做做对比;(所有说session是依赖于cookie的,cookie可以单独存在session不可以独立存在);
#! /usr/bin/env python
# *-* coding: utf-8 *-*
from datetime import timedelta
from flask import Flask
from flask import session app = Flask(__name__)
app.config["SECRET_KEY"] = "abcdefg" # app.secret_key["SECRET_KEY"] = "abcsefght" @app.route('/index')
def index():
user_name = session.get("user_name")
user_id = session.get("user_id")
return "%s---%s" % (user_name, user_id) @app.route("/login")
def login():
session.permanent = True
app.permanent_session_lifetime = timedelta(second=10)
session["user_name"] = "xiaomingh"
session["user_id"] = ""
return "session设置成功" @app.route("/logout")
def logout():
session.pop("user_name", None)
session.pop("user_id", None)
return "session删除删除成功" if __name__ == '__main__':
app.run(debug=True)
session的设置
思考:在视图函数中,如何取到当前请求的相关数据?比如:请求地址,请求方式,cookie等等
在 flask 中,可以直接在视图函数中使用 request 这个对象进行获取相关数据,而 request 就是请求上下文的对象,保存了当前本次请求的相关数据,请求上下文对象有:request、session
- request
- 封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get('user'),获取的是get请求的参数。
- session
- 用来记录请求会话中的信息,针对的是用户信息。举例:session['name'] = user.id,可以记录用户信息。还可以通过session.get('name')获取用户信息。
- request
应用上下文(application context)
它的字面意思是 应用上下文,但它不是一直存在的,它只是request context 中的一个对 app 的代理(人),所谓local proxy。它的作用主要是帮助 request 获取当前的应用,它是伴 request 而生,随 request 而灭的。
应用上下文对象有:current_app,g
current_app
应用程序上下文,用于存储应用程序中的变量,可以通过current_app.name打印当前app的名称,也可以在current_app中存储一些变量,例如:
- 应用的启动脚本是哪个文件,启动时指定了哪些参数
- 加载了哪些配置文件,导入了哪些配置
- 连了哪个数据库
- 有哪些public的工具类、常量
- 应用跑再哪个机器上,IP多少,内存多大
current_app.name
current_app.test_value='value'
g变量
g 作为 flask 程序全局的一个临时变量,充当者中间媒介的作用,我们可以通过它传递一些数据,g 保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread id区别
flask_script
#! /usr/bin/env python
# *-* coding: utf-8 *-* from flask import Flask
# 请求上下文的变量
from flask import request, make_response
# 运用上下文的变量
from flask_script import Manager
from flask import current_app
from flask import g app = Flask(__name__)
app.debug = True
manager = Manager(app) @app.route('/')
def hello_world():
# 类似于一个全局变量的东西
print(current_app.config.get("DEBUG"))
return 'Hello World!' if __name__ == '__main__':
manager.run()
# app.run(debug=True)
通过使用Flask-Script扩展,我们可以在Flask服务器启动的时候,通过命令行的方式传入参数。而不仅仅通过app.run()方法中传参,比如我们可以通过:
python hello.py runserver -host ip地址
flask内容的更多相关文章
- Flask -- 内容管理系统
例子: # content_manager.py # 把TOPIC存在一个字典里,key为关键字,value为二维数组# TOPIC_DICT['Django'][0]为Title,TOPIC_DIC ...
- flask内容学习之蓝图以及单元测试
蓝图的概念: 简单来说,蓝图是一个存储操作方法的容器.这些操作在这个蓝图被注册到一个应用之后就可以被调用.Flask可以通过蓝图来制止URL以及处理请求.Flask使用蓝图来让应用实现模块化,在Fla ...
- flask内容之数据库的管理
#! /usr/bin/env python # *-* coding: utf-8 *-* from flask import Flask, flash, redirect from flask i ...
- flask内容学习第三天(flak中的csrf跨站请求)
问题一:什么是csrf? 英文全称Cross Site Request Forgery(跨站请求伪造): 通俗来讲就是攻击者盗用你的身份,冒用你的名义发出恶意请求,包括发送邮件,电话信息,甚至于转账或 ...
- Python轻量Web框架Flask使用
http://blog.csdn.net/jacman/article/details/49098819 目录(?)[+] Flask安装 Python开发工具EclipsePyDev准备 Flask ...
- 结合docker做flask+kafka数据接口与压力测试
一.需求 需要做实时数据接入的接口.数据最终要写入库,要做到高并发,数据的完整,不丢失数据. 二.技术选型 1.因为只是做简单的接口,不需要复杂功能,所以决定用flask这个简单的python框架(因 ...
- FlaskWeb开发从入门到放弃(二)
第5章 章节五 01 内容概要 02 内容回顾 03 面向对象相关补充:metaclass(一) 04 面向对象相关补充:metaclass(二) 05 WTforms实例化流程分析(一) 06 WT ...
- jsonify返回中文乱码的问题
参考博客: 解决flask中文乱码的问题 返回内容如图: 实际填写的内容: 从网上找答案,结果很多都是说配置app.config,如下: app.config['JSON_AS_ASCII'] 但我试 ...
- ubuntu16.04设置开机自启服务
网上说了开机自启有许多种方法: 1.最简单的是:在/etc/rc.local的exit 0前面加上你启动服务的脚本文件路径 注:这个脚本文件应写绝对路径! 2.网上:修改rc.local开头的#/bi ...
随机推荐
- Windows Azure 搭建网络代理 Proxy
额 题目起的有点大 其实就是在 Linux 上使用代理 不过是用的 Azure 上的 Liunx 虚拟机而已 如何在 Azure 上搭建 VPN 见上篇:http://www.cnblogs.com/ ...
- 【BZOJ2402】陶陶的难题II 分数规划+树链剖分+线段树+凸包
题解: 首先分数规划是很明显的 然后在于我们如何要快速要求yi-mid*xi的最值 这个是看了题解之后才知道的 这个是斜率的一个基本方法 我们设y=mid*x+z 那么显然我们可以把(x,y)插入到一 ...
- drone的pipeline原理与代码分析
最近的一个项目,需要实现一个工作任务流(task pipeline),基于之前CICD的经验,jenkins pipeline和drone的pipeline进入候选. drone是基于go的cicd解 ...
- MyEclipse 8.6 下载
Downloads: MyEclipse 8.6 for Eclipse Galileo Windows http://downloads.myeclipseide.com/downloads/pro ...
- k8s 廖老师的分享
https://mp.weixin.qq.com/s/7o8QxGydMTUe4Q7Tz46Diw
- CentOS 7.2配置Apache服务httpd小伙伴们可以参考一下
这篇文章主要为大家详细介绍了CentOS 7.2配置Apache服务 httpd上篇,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 一.Perl + mod_perl 安装mod_perl使Per ...
- JavaSE | Lambda| Optional| Stream API
JDK1.8新特性 1.接口:默认方法. 静态方法 2.Lambda表达式和StreamAPI 3.Optional类 4.新的日期时间API Lambda表达式:为了简化代码,使得Java支持 St ...
- 查找常用字符(给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表。例如,如果一个字符在每个字符串中出现 3 次,但不是 4 次,则需要在最终答案中包含该字符 3 次。)
给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表. 例如,如果一个字符在每个字符串中出现 3 次,但不是 4 次,则需要在最终答案中包含该字符 ...
- 一个小demo 实用selenium 抓取淘宝搜索页面内的产品内容
废话少说,上代码 #conding:utf-8 import re from selenium import webdriver from selenium.webdriver.common.by i ...
- XamarinEssentials教程移除键值首选项的键值
XamarinEssentials教程移除键值首选项的键值 如果开发者不再使用首选项中的某一项时,可以将该项移除掉.此时可以使用Preferences类的Remove()方法,该方法可以将存在于首选项 ...