标签:主机 字符创 配置 404错误 ret ESS 接收 converter 本质
为了不与现行项目想冲突,通常情况下会引入一个虚拟环境,将Flask安装在虚拟环境下,虚拟环境用virtualenv
使用Virtualenv创建虚拟环境
将Flask安装在该虚拟环境里
或者不配置直接
pip install flask
#Flask依赖一个实现wsgi协议的模块:werkzeug
from werkzeug.wrappers import Request, Response
@Request.application
def hello(request):
return Response('Hello World!')
if __name__ == '__main__':
from werkzeug.serving import run_simple
run_simple('localhost', 4000, hello)
flask依赖于wsgi,实现wsgi模块,wsgiref,werkzeug,uwsgi
from flask import Flask
# 1 创建一个Flask实例
app = Flask(__name__)
@app.route('/') # 路由系统生成,视图对应url
def first_flask(): # 视图函数
return 'Hello World'
if __name__ == '__main__':
app.run() # 启用socket
flask初始化配置
static_folder = 'static', # 静态文件目录的路径 默认当前项目中的static目录
static_host = None, # 远程静态文件所用的Host地址,默认为空
static_url_path = None, # 静态文件目录的url路径 默认不写是与static_folder同名,远程静态文件时复用
# host_matching是否开启host主机位匹配,是要与static_host一起使用,如果配置了static_host, 则必须赋值为True
# 这里要说明一下,@app.route("/",host="localhost:5000") 就必须要这样写
# host="localhost:5000" 如果主机头不是 localhost:5000 则无法通过当前的路由
host_matching = False, # 如果不是特别需要的话,慎用,否则所有的route 都需要host=""的参数
subdomain_matching = False, # 理论上来说是用来限制SERVER_NAME子域名的,但是目前还没有感觉出来区别在哪里
template_folder = 'templates' # template模板目录, 默认当前项目中的 templates 目录
instance_path = None, # 指向另一个Flask实例的路径
instance_relative_config = False # 是否加载另一个实例的配置
root_path = None # 主模块所在的目录的绝对路径,默认项目目录
更改配置文件
app.config.from_object('settings.Base') # 更改配置文件
通过路径,找到类并获取类中的静态字段
配置文件
@app.route('url地址',methods=['POST',"GET"],endpoint='别名',defaults={'nid':1},strict_slashes=True,redirect_to='/index')
endpoint:反向生成url,默认是函数名
endpoint= 相当于django中的name
url_for 相当于 reverse 不定义默认是函数名
defaults:默认参数
strict_slashes:True 严格要求访问的方式,
redirect_to='url':301重定向:永久重定向
接收字符串类型
from flask import Flask
app=Flask(__name__)
@app.route('/<name>') #设置url传参数
def first_flask(name): #视图必须有对应接收参数
print(name)
return 'Hello World' #response
if __name__ == '__main__':
app.run()
接收int,float,接收path链接类型
# int类型
@app.route('/<int:age>/')
# float类型
@app.route('/<float:salary>/')
# path类型
@app.route('/<path:url>/')
def first(url): # 视图必须要对应接收参数
pass
指定允许的请求方法
@app.route('/<path:url>/',methods=['get']) #只允许get请求
通过别名反向生成url
from flask import Flask,url_for
app=Flask(__name__)
@app.route('/<path:url>',endpoint='name1') #设置别名
def first_flask(url):
print(url_for('name1',url=url)) #如果设置了url参数,url_for(别名,加参数)
return 'Hello World'
if __name__ == '__main__':
app.run()
from flask import Flask, views, url_for
from werkzeug.routing import BaseConverter
app = Flask(import_name=__name__)
class RegexConverter(BaseConverter):
"""
自定义URL匹配正则表达式
"""
def __init__(self, map, regex):
super(RegexConverter, self).__init__(map)
self.regex = regex
def to_python(self, value):
"""
路由匹配时,匹配成功后传递给视图函数中参数的值
:param value:
:return:
"""
return int(value)
def to_url(self, value):
"""
使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
:param value:
:return:
"""
val = super(RegexConverter, self).to_url(value)
return val
# 添加到flask中
app.url_map.converters['regex'] = RegexConverter
@app.route('/index/<regex("\d+"):nid>')
def index(nid):
print(url_for('index', nid='888'))
return 'Index'
if __name__ == '__main__':
app.run()
FBV
from flask import Flask,render_template
app = Flask(__name__)
# 导入配置
app.config.from_object('settings.类名')
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run()
CBV (不常用)
# 1.导入views
from flask import views
# 写一个类,与django中类似
class User(views.methodView):
methods = ['GET']
decorators = ['装饰器']
def dispatch_request(self,*args,**kwargs):
pass
def get(self):
self.dispatch_request()
pass
def post(self):
pass
# 加入app中
app.add_url_rule('/user/', view_func=User.as_view(name='endpoint'))
request.form #存放form表单中的序列化数据
request.args # 存放url里面的序列化数据
request.values.to_dict() # 存放url和from中的所有数据
request.method # 存放请求方式
request.path # 路由地址
request.url 所有的url:全部地址
request.host 主机位 127.0.0.1:5000
request.host_url 将主机位转换成url http://127.0.0.1:5000/
request.data 查看传过来所有解析不了的内容
request.json 查看前端传过来的json文件
request.headers 查看所有的请求头
file = request.files 前端传过来的文件
file.filename 返回文件名称
file.save() :保存文件
return '字符窜'
return render_template() # 返回一个页面
return redirect() # 重定向
return jsonify # 返回json数据,返回标准的json格式字符串 content-type: application/json
{{ }} 引用变量 非逻辑代码时使用
{% %} 逻辑代码使用
-基本数据类型,可以执行python语法,如dict.get(),list[11]
-传入函数
django,可以执行
flask,不自动执行
-全局定义
@app.template_global()
@app.template_filter()
-定义模板
{% extends %} 引入模板
{% include %} 引入一小部分
-宏定义
{% macro ccc(name,type='text',value='') %}
<input type="{{ type }}" name={{ name }} value={{ value }}>
<input type="button" value="提交">
{% endmacro %}
{{ ccc('name') }} 运行
-安全
-前端 {{ll|safe}}
-后端 Markup('字符串')
# 1导入session
from flask import session
# 2需要对其进行加盐,也可以在配置文件中对其加盐
app.secret_key = 'alfkjs'
# 3存session
session['key'] = value
# 4取值
session.get('key', None)
闪现,在session中存储一个数据,读取时通过pop将数据移出,
flash('内容', category= 'ok')
# 第一个存的内容
# category 是别名,相当于分lei
get_flashed_messages() # 取所有
# 获取flash中的值,
# get_flashed_messages()中的参数:
with_categories=True # True表示返回一个元祖
category_filter='ok' #取出别名为ok的所有参数,放在一个列表中
# 如果想将列表发送到前段,需要导入jsonify
应用场景
假设在A页面做个操作,但该操作失败了,要跳转到B页面并显示这些错误信息
from flask import Flask,flash,get_flashed_messages,request,redirect
app = Flask(__name__)
app.debug = True
app.secret_key="1234"
@app.route("/index")
def index():
# get请求用request.args.get, v是接受参数的变量
# 浏览器请求:
val = request.args.get('v')
if val =="body":
return "hello World, guys"
# 如果请求参数不是body,则跳转到错误页面,需要将错误信息flash,也就是设置错误值到某个地方
# A.flash不分类,直接设置值
flash("前端输入参数错误")
# B.flash还可以对错误信息,进行分类
flash("前端输入参数错误", category="x1")
return redirect("/error")
@app.route("/error")
def error():
'''
显示错误信息
'''
# 跳转到error页面后,请求时获取错误信息
# A.flash没有分类时
# data = get_flashed_messages() # 获取的就是flash的值
# B. 对于有分类的,取值时可以通过 category_filter 根据分类取错误信息
data = get_flashed_messages(category_filter=['x1'])
# 可能有很多的错误信息,也可以按照索引的方式取出错误值
if data:
msg = data[0]
else:
msg = "..."
return "错误信息:%s" %(msg)
if __name__=="__main__":
app.run()from flask import Flask,flash,get_flashed_messages,request,redirect
app = Flask(__name__)
app.debug = True
app.secret_key="1234"
@app.route("/index")
def index():
# get请求用request.args.get, v是接受参数的变量
# 浏览器请求:
val = request.args.get('v')
if val =="body":
return "hello World, guys"
# 如果请求参数不是body,则跳转到错误页面,需要将错误信息flash,也就是设置错误值到某个地方
# A.flash不分类,直接设置值
flash("前端输入参数错误")
# B.flash还可以对错误信息,进行分类
flash("前端输入参数错误", category="x1")
return redirect("/error")
@app.route("/error")
def error():
'''
显示错误信息
'''
# 跳转到error页面后,请求时获取错误信息
# A.flash没有分类时
# data = get_flashed_messages() # 获取的就是flash的值
# B. 对于有分类的,取值时可以通过 category_filter 根据分类取错误信息
data = get_flashed_messages(category_filter=['x1'])
# 可能有很多的错误信息,也可以按照索引的方式取出错误值
if data:
msg = data[0]
else:
msg = "..."
return "错误信息:%s" %(msg)
if __name__=="__main__":
app.run()
请求 执行前会执行一个wsgi_app,所以这里就是重写这个方法
from flask import Flask
app = Flask(__name__)
@app.route("/login", methods=['GET', 'POST'])
def index():
pass
class Md(object):
def __init__(self, old_wsgi_app):
self.old_wsgi_app = old_wsgi_app
def __call__(self, environ, start_response):
print("开始之前")
ret = self.old_wsgi_app(environ, start_response)
print("结束之后")
return ret
if __name__ =="__main__":
app.wsgi_app = Md(app.wsgi_app) # 相当于把wsgi_app给更新了
app.run()
蓝图的作用,就是将功能和主服务分开.
简单理解就是用蓝图实例化一个对象,然后由这个对象写一个函数,再加入flask中
使用蓝图的目标:
\1. 构造程序目录
\2. 自定义程序目录
批量处理url
定制模板路径和静态文件路径
请求扩展:
- 可以针对app, 即全部程序都生效
- 也可以针对单个的蓝图,即只有在执行该蓝图时,请求扩展才会生效
简单实例:
目录结构
s_view.py中内容
from flask import Blueprint # 导入 Flask 中的蓝图 Blueprint 模块
sv = Blueprint("sv", __name__) # 实例化一个蓝图(Blueprint)对象
@sv.route("/svlist") # 这里添加路由和视图函数的时候与在Flask对象中添加是一样的
def view_list():
return "svlist_view_list"
manager.py中的内容
from flask import Flask
# 导入此前写好的蓝图模块
from student_view import s_view
app = Flask(__name__) # type:Flask
# 在Flask对象中注册蓝图模块中的蓝图对象 s_view 中的 sv
app.register_blueprint(s_view.sv)
app.run("0.0.0.0",5000)
# 现在Flask对象中并没有写任何的路由和视图函数
然后开启服务,就可以访问了http://127.0.0.1:5000/svlist
详情:请查看博客: https://www.cnblogs.com/95lyj/p/9509229.html
@app.template_global() 全局函数
@app.template_filter() 类似标签
@app.before_request 类似于process_request:没有参数 顺序:从上到下
@app.after_request 类似于process_response:必须有参数,并返回 顺序:从下到上:即使在第一个就返回,也会全部执行一遍
@app.before_first_request 只有第一次执行
@app.teardown_request 在有异常发生时触发
@app.errorhandler(404) 没找到页面走这个之下的函数,有一个参数
@app.before_request
def process_request(*args, **kwargs):
# 验证表示,任何地址请求都会先执行before_request,所以登录验证就可以在before_request里做用户认证功能了
print("其他请求之前就执行了process_request")
# 4.访问/login的时候还没有登录,就会一直重定向到登录页,所以就要设置个白名单,如果请求地址是/login,就返回None
if request.path == "/login":
return None
# 1.登录验证功能
user = session.get('user_info')
# 2.如果登录信息正常,什么都不做,程序继续其他执行
if user:
return None
# 3.如果登录验证不通过,就重定向到登录页面
return redirect("/login")
在请求进入视图函数之前执行,与他作用相同的@app.before_first_request也是,不同点是这个只执行一次,而after_request可以执行多次,按照顺序执行
@app.after_request
def foot_log(environ):
if request.path != "/login":
print("有客人访问了",request.path)
return environ
注意:
但是要注意,多个请求扩展的执行顺序是有差别的:
对于before_request,是按照写的代码的顺序从上到下的顺序正序执行的
对于after_request, 是按照写的代码的顺序从下到上的顺序倒序执行的
如果before_request return了(即程序被拦截了),其他before_request就不执行了,但是所有的after_request都会继续执行
实例
from flask import Flask,render_template,request,redirect,session,url_for
app = Flask(__name__)
app.debug = True
app.secret_key = 'siuljskdjfs'
@app.before_request
def process_request1(*args,**kwargs):
print('process_request1 进来了')
return "拦截"
@app.before_request
def process_request2(*args,**kwargs):
print('process_request2 进来了')
@app.after_request
def process_response1(response):
print('process_response1 走了')
# after_request 必须返回 response
return response
@app.after_request
def process_response2(response):
print('process_response2 走了')
return response
# 视图函数
@app.route('/index',methods=['GET'])
def index():
print('index函数')
return "Index"
if __name__ == '__main__':
app.run()
执行结果:
from flask import Flask,render_template,request,redirect,session,url_for
app = Flask(__name__)
app.debug = True
app.secret_key = 'siuljskdjfs'
# 经常会出现url不存在的情况,一般会有错误信息
# 而这个错误信息也是可以进行定制的,根据错误码定制错误信息方法如下:
@app.errorhandler(404)
def error_404(arg):
return "404错误了"
# 视图函数
@app.route('/index',methods=['GET'])
def index():
print('index函数')
return "Index"
if __name__ == '__main__':
app.run()
from flask import Flask,request
app = Flask(__name__)
app.debug = True
# 这就是基于请求扩展的 定制模板方法
# 相对于在模板里定制了一个函数
@app.template_global()
def sb(a1, a2):
return a1 + a2
if __name__ == '__main__':
app.run()
#在HTML里调用的方式如下:
{{sb(1,2)}}
from flask import Flask,request
app = Flask(__name__)
app.debug = True
# 这就是基于请求扩展的 定制模板方法
@app.template_filter()
def db(a1, a2, a3):
return a1 + a2 + a3
if __name__ == '__main__':
app.run()
#在HTML里调用的方式如下:
{{ 1|db(2,3)} # 参数 a1 = 1,是第一个参数; a2=2 是第二个参数; a3=3 是第三个参数
应用场景:数据库的连接,初始化操作
from flask import Flask,request
app = Flask(__name__)
app.debug = True
# 内部其实就有个判断,初始值是FALSE,第一次执行后将值改变为True,以后判断后就不执行了
@app.before_first_request
def before_first_request2():
print('before_first_request2')
if __name__ == '__main__':
app.run()
标签:主机 字符创 配置 404错误 ret ESS 接收 converter 本质
原文地址:https://www.cnblogs.com/yuncong/p/10200325.html