为了避免与现行项目想冲突,一般状况下会引入一个虚拟环境,将Flask安装在虚拟环境下,虚拟环境用virtualenvhtml
使用Virtualenv建立虚拟环境前端
将Flask安装在该虚拟环境里python
或者不配置直接web
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 # 主模块所在的目录的绝对路径,默认项目目录
更改配置文件django
app.config.from_object('settings.Base') # 更改配置文件
经过路径,找到类并获取类中的静态字段json
配置文件flask
@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()