Flask
2018-09-01 05:53:19来源:博客园 阅读 ()
Flask攻略
python三大框架预览
Python Web框架分类 功能分类: a:收发消息相关(socket) b:根据不同的URL执行不同的函数(业务逻辑相关的) c:实现动态网页(字符串的替换) Web框架分类: 1、自己实现b,c,使用第三方的a(Django) 2、自己实现b,使用第三方的a,c(Flask) 3、自己实现a\b\c(Tornado) 两个模块 web服务器程序 《---WSGI协议---》 web应用程序 1、wsgiref Django开发环境使用的就是wsgiref模块 2、jinja2(Flask) 渲染HTML页面,其实就是实现字符串的替换
python三大框架优缺点
Flask:
优点: 小而精,短小精悍,第三方组件特别多
缺点: 组件更新速度取决于开源者
Tornado:
优点: 原生的WebSocket, 异步任务, IO非阻塞玩
缺点: 没有组件,Session都没有
Django:
优点: 大而全,组件非常全面
缺点: 太大,重量级框架,加载太大,浪费资源
Flask的优势
Flask中的Werkzuge原理,__call__() Flask的第一个Hello Flask Flask的 HTTPresponse render_template redirect Flask中的 request Flask中的 Jinja2 ,Markup Flask中的 session secret_key Flask中的路由系统 url_for
Flask中Werkzuge原理
from werkzeug.wrappers import Response, Request from werkzeug.serving import run_simple # application源码里面 get_wsgi_headers 里面有个__call__方法 # 可以调用__call__ 在执行flk的时候执行call里面的结果 @Request.application def flk(r): print(r.url) if r.url == '/123': asd() return Response("hello") # flk run_simple("127.0.0.1", 5500, flk) def asd(): print('kermit') asd()
Flask三剑客
# HTTPresponse: return "Hello Flask" # render_template: return render_template("login.html") #templates # redirect: return redirect("/login")
示例:
# Httpresponse @app.route("/index") def index(): return "Hello Flask" # render_template @app.route("/login") def login(): return render_template("login.html") # redirect @app.route("/") def root_path(): return redirect("/login")
Flask需要自己开启:(流程如下)
from flask import Flask, render_template, redirect app = Flask(__name__) app.run() # 可以自定义ip 端口 和debug模式
Flask的request
request.method 获取请求方式 request.form 获取FromData数据(通常情况下的POST请求) request.args 获取GET方式提交的数据 request.files 获取file request.url_about 获取所有的关于URL的参数 request.values 获取全部提交方式 to_dict 坑,覆盖,GET覆盖POST request.headers 获取头部信息 request.cookie 获取客户端cookie request.json 数据头:application/json request.data 在没有任何数据头的情况提交的POST
Flask的模板语言
# Flask 基于 Jinja2 做了一层小的封装,向前端传递数据 render_template 参数传递 stu = {k1:v1} {{ stu }} <td>{{ stu.name }}</td> <td>{{ stu["age"] }}</td> {% if stu.get("gender") == "中" %} <td>男</td> {% else %} <td>{{ stu.get("gender") }}</td> {% endif %} STUDENT_LIST = [ {'name': 'stu1', 'age': 38, 'gender': '中'}, {'name': 'stu2', 'age': 73, 'gender': '男'}, {'name': 'stu3', 'age': 84, 'gender': '女'} ] <td>{{ stu.0.name }}</td> <td>{{ stu[0]["age"] }}</td> {% if stu[0].get("gender") == "中" %} <td>男</td> {% else %} <td>{{ stu.0.get("gender") }}</td> {% endif %} @apl.template_global() def a_b_sum(a,b): return a+b {{ a_b_sum(123,234) }} @apl.template_filter() def a_b_c_sum(a,b,c): return a+b+c {{ 123 | a_b_c_sum(1,2) }}
注意:安全字符串,Markup相当于模板里面有safe
{{ input | safe }} Markup() : Markup("<input type='text' name='input_tag'>")
pycharm识别模板语言的格式:设置jinja2的语言
Session
secret_key = "" 这个是开启session必备的参数
form flask import session app.secret_key = "随意" session["user"] = "xxxx" if session.get("user")
Jsonify
json的转换兼容性比json模块强
from flask import jsonify # import json # Flask的jsonify是等同于json # 区别是json的转换兼容性比json模块强 @flk.route('/json') def get_json(): res = { "user_id": 1, "username": "kermit", "password": "123" } # return json.dumps(res) return jsonify(res)
Flask路由
flk.route() "/index" 路由地址 "/index/<nid>" 动态路由地址(视图函数需要nid参数) "/index/<int:nid>" 动态路由地址 "/files/<filename>" <> 里面的filename可以是本地文件内的任何一个文件全名,可以把任意存在的文件内容打印到页面上
# 可以把所有文件内容显示到页面上面 @flk.route('/files/<filename>') def files(filename): return send_file(filename)
补充
methods=["GET","POST"] 允许URL的请求方式 endpoint="index" 反向URL操作,可以解决Inner重名的问题 redirect_to="/index2" 服务器端页面跳转 301永久性重定向 strict_slashes=False 可以使用"/"结尾 反之不可以 defaults={"nid":1} 视图函数默认参数
Flask配置
settings.FlaskSettings
DEBUG = True app.config["secret_key"] = "xxxxx" TESTING = True { 'DEBUG': False, # 是否开启Debug模式 'TESTING': False, # 是否开启测试模式 'PROPAGATE_EXCEPTIONS': None, # 异常传播(是否在控制台打印LOG) 当Debug或者testing开启后,自动为True 'PRESERVE_CONTEXT_ON_EXCEPTION': None, # 一两句话说不清楚,一般不用它 'SECRET_KEY': None, # 之前遇到过,在启用Session的时候,一定要有它 'PERMANENT_SESSION_LIFETIME': 31, # days , Session的生命周期(天)默认31天 'USE_X_SENDFILE': False, # 是否弃用 x_sendfile 'LOGGER_NAME': None, # 日志记录器的名称 'LOGGER_HANDLER_POLICY': 'always', 'SERVER_NAME': None, # 服务访问域名 'APPLICATION_ROOT': None, # 项目的完整路径 'SESSION_COOKIE_NAME': 'session', # 在cookies中存放session加密字符串的名字 'SESSION_COOKIE_DOMAIN': None, # 在哪个域名下会产生session记录在cookies中 'SESSION_COOKIE_PATH': None, # cookies的路径 'SESSION_COOKIE_HTTPONLY': True, # 控制 cookie 是否应被设置 httponly 的标志, 'SESSION_COOKIE_SECURE': False, # 控制 cookie 是否应被设置安全标志 'SESSION_REFRESH_EACH_REQUEST': True, # 这个标志控制永久会话如何刷新 'MAX_CONTENT_LENGTH': None, # 如果设置为字节数, Flask 会拒绝内容长度大于此值的请求进入,并返回一个 413 状态码 'SEND_FILE_MAX_AGE_DEFAULT': 12, # hours 默认缓存控制的最大期限 'TRAP_BAD_REQUEST_ERRORS': False, # 如果这个值被设置为 True ,Flask不会执行 HTTP 异常的错误处理,而是像对待其它异常一样, # 通过异常栈让它冒泡地抛出。这对于需要找出 HTTP 异常源头的可怕调试情形是有用的。 'TRAP_HTTP_EXCEPTIONS': False, # Werkzeug 处理请求中的特定数据的内部数据结构会抛出同样也是“错误的请求”异常的特殊的 key errors 。 # 同样地,为了保持一致,许多操作可以显式地抛出 BadRequest 异常。 # 因为在调试中,你希望准确地找出异常的原因,这个设置用于在这些情形下调试。 # 如果这个值被设置为 True ,你只会得到常规的回溯。 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', # 生成URL的时候如果没有可用的 URL 模式话将使用这个值 'JSON_AS_ASCII': True, # 默认情况下 Flask 使用 ascii 编码来序列化对象。如果这个值被设置为 False , # Flask不会将其编码为 ASCII,并且按原样输出,返回它的 unicode 字符串。 # 比如 jsonfiy 会自动地采用 utf-8 来编码它然后才进行传输。 'JSON_SORT_KEYS': True, #默认情况下 Flask 按照 JSON 对象的键的顺序来序来序列化它。 # 这样做是为了确保键的顺序不会受到字典的哈希种子的影响,从而返回的值每次都是一致的,不会造成无用的额外 HTTP 缓存。 # 你可以通过修改这个配置的值来覆盖默认的操作。但这是不被推荐的做法因为这个默认的行为可能会给你在性能的代价上带来改善。 'JSONIFY_PRETTYPRINT_REGULAR': True, 'JSONIFY_MIMETYPE': 'application/json', 'TEMPLATES_AUTO_RELOAD': None, }
蓝图(Blueprint)
from flask import Blueprint,render_template,redirect reg = Blueprint("reg",__name__,template_folder="reg_temp",static_folder="regs",static_url_path="/regs")
@reg.route("/reg") def reg_user(): return render_template("reg_index.html")
from flask import Flask import reg_user app = Flask(__name__) app.register_blueprint(reg_user.reg) if __name__ == '__main__': app.run("0.0.0.0", 9527, debug=True)
1.Flask实例配置
app.config.form_object("setting.FlaskSetting")
app.DEBUG = True 开启Debug模式,该完代码不用手动重启
app.SECRET_KEY = "xxxxx" 开启session必备参数
2.初始化配置(Flask,Blueprint)
template_folder="reg_temp",
static_folder="regs",
static_url_path="/regs"
3.蓝图Blueprint
在app实例中注册蓝图app.register_blueprint(reg_user.reg)
实例化蓝图对象reg = Blueprint("reg",__name__,template_folder="reg_temp",static_folder="regs",static_url_path="/regs")
蓝图对象同样与Flask对象,具备独立模板和静态目录
from flask import Blueprint, render_template, redirect import DATA student_list = Blueprint('student_list', __name__, static_folder="list_static", static_url_path="/list_static") # 蓝图实例对象一定不能与视图函数同名 @student_list.route('/list') def list(): return render_template('index.html')
4.before_request after_request before_frist_request
before_request 在请求进入视图函数之前做出的处理
after_request 在视图函数返回给用户之前做出的处理
before_frist_request 在第一次请求进入视图函数之前做出的处理
# 类似于Django中间件的功能 @flk.before_request # 在请求之前 def be1(): print('在请求进入App之前做出处理') # 判断url是不是/login if request.path == "/login": print('当前访问的页面url是:', request.path) # True返回None不作任何操作往下走 return None if session.get("user"): print('userSession存在,直接访问页面!') return None else: print('user不存在,跳转到login页面') return redirect("/login") @flk.before_request def be2(): print('执行be2') # 在请求之后 @flk.after_request def af1(response): print('在此时执行了after1') return response @flk.after_request def af2(response): print('在此时执行了after2') return response # 第一次请求前执行 @flk.before_first_request def be_first(): print('第一次请求') # 报错发送的状态码显示的结果 @flk.errorhandler(404) def error_page(arg): return "当前页面不存在!"
5.errorheadler(404)
def error_page(arg)
错误信息头
第一个Flask
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/08/27 17:19 # @Author : MJay_Lee # @File : flask_demo_test.py # @Contact : limengjiejj@hotmail.com from flask import Flask # 导入Flask类 app = Flask(__name__) # 实例化Flask对象 app @app.route("/") # app中的route装饰器 def index(): # 视图函数 return "first flask app" app.run("0.0.0.0",5000,debug=True) # 启动Flask Web 服务
Flask三剑客
Flask中的HTTPResponse
在Flask中的HTTPResponse,在我们看来其实就是直接返回字符串
from flask import Flask app = Flask(__name__) @app.route('/') # 路由 def index(): # 视图 return "Hello Flask" # HTTPResponse
Flask中的redirect
from flask import Flask,redirect app = Flask(__name__) @app.route('/') def index(): return "Hello Flask" @app.route('/redi') # app中的route装饰器,用来指定视图函数的URL地址 def redi(): # 视图函数 return redirect('/') # redirect 跳转至 '/' app.run("0.0.0.0",5500,debug=True)
Flask中的render(render_template)
from flask import Flask,redirect,render_template app = Flask(__name__) @app.route('/') def index(): return "Hello Flask" @app.route('/redi') def redi(): return redirect('/') @app.route("/home") # app中route装饰器,用来指定视图函数的url地址 def home(): # home 视图函数 return render_template("home.html") # 渲染HTML模板发安徽HTML页面 app.run("0.0.0.0",5500,debug=True)
注意:如果要使用render_template返回渲染的模板,请在项目的主目录中加入一个目录templates文件夹
Flask中的request
每个框架中都有处理请求或收发消息的机制(request),而每个框架都有异同
一个form表单post的提交方式
html文件
<form action="" method="post" novalidate> <input type="text" name="user" id=""> <input type="password" name="pwd" id=""> <input type="submit" value="提交">
py文件
@app.route("/home",methods=["GET","POST"]) # app中route装饰器,用来指定视图函数的url地址 def home(): # home 视图函数 if request.method == "POST": print(request.method) # POST print(request.form) # ImmutableMultiDict([('user', 'lmj'), ('pwd', '123')]) print(request.form['user']) # lmj print(request.form['pwd']) # 123 print(list(request.form.keys())) # ['user', 'pwd'] return "POST请求已受理" return render_template("home.html") # 渲染HTML模板
methods=["GET","POST"]代表这个URL地址只允许请求的方式,是个列表
request的参数获取
那么request的参数获取的几个方式
html文件
<form action="/home?id=1&age=18" method="post" novalidate> <input type="text" name="user" id=""> <input type="password" name="pwd" id=""> <input type="submit" value="提交">
py文件
@app.route("/home",methods=["GET","POST"]) # app中route装饰器,用来指定视图函数的url地址 def home(): # home 视图函数 if request.method == "POST": print(request.form) # form表单中的参数 print('request.args'.center(50,"=")) print(list(request.args)) # url中的参数 print('request.values'.center(50,"=")) print(list(request.values)) # 所有参数 print('request.values.to_dict'.center(50,"=")) print(request.values.to_dict()) # 将参数转为字典 return "POST请求已受理" return render_template("home.html") # 渲染HTML模板发安徽HTML页面
结果
===================request.args=================== ['id', 'age'] ==================request.values================== ['id', 'age', 'pwd', 'user'] ==============request.values.to_dict============== {'user': 'lmj', 'pwd': '123', 'id': '1', 'age': '18'}
注意:
# 注意这里的坑来啦! 坑来啦! # 如果url和form中的Key重名的话,form中的同名的key中value会被url中的value覆盖 # http://127.0.0.1:5500/req?id=1&user=cly print(request.values.to_dict()) # {'user': cly'pwd': '123', 'id': '1'}
request.cookies
print(request.cookies) """ { 'csrftoken': 'elPT8HW8Zw74NPSftY0suJEqbm3cOxEPl05f1oezHN61kikgqOgcuXWtiJCyhtuX', 'sessionid': 'cqfjxs0svrq2nqf9i4hdghdvqep6468w' } """
request.headers,请求头中的参数
print(type(request.headers)) # <class 'werkzeug.datastructures.EnvironHeaders'> print(request.headers) ''' Host: 127.0.0.1:5500 Connection: keep-alive Content-Length: 16 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 Origin: http://127.0.0.1:5500 Content-Type: application/x-www-form-urlencoded Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Referer: http://127.0.0.1:5500/home Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,und;q=0.8,en;q=0.7 Cookie: csrftoken=elPT8HW8Zw74NPSftY0suJEqbm3cOxEPl05f1oezHN61kikgqOgcuXWtiJCyhtuX; sessionid=cqfjxs0svrq2nqf9i4hdghdvqep6468w '''
request.data,若处理不了的就变成字符串存在data里
可以request.data,json.loads同样可以拿到里面的数据
你一定要知道 request 是基于 mimetype 进行处理的 mimetype的类型 以及 字符串儿 : http://www.w3school.com.cn/media/media_mimeref.asp 如果不属于上述类型的描述,request就会将无法处理的参数转为Json存入到 data 中
request.files,文件上传
遇到文件上传,request.files村的就是上传的文件,但Flask在这个文件的操作中加了封装
html文件
<form action="" method="post" enctype="multipart/form-data" novalidate> <input type="file" name="file"> <input type="submit" value="提交"> </form>
py文件
@app.route("/home",methods=["GET","POST"]) def home(): if request.method == "POST": print(request.files) # ImmutableMultiDict([('file', <FileStorage: '待整理内容.txt' ('text/plain')>)]) print(request.files["file"]) # <FileStorage: '待整理内容.txt' ('text/plain')> my_file = request.files["file"] my_file.save("upload_file.txt") # 保存文件,里面可以写完整路径+文件名 return "POST请求已受理" return render_template("home.html")
request的路径获取
# 获取当前的url路径 print(request.path)# /home # 当前url路径的上一级路径 print(request.script_root) # # 当前url的全部路径 print(request.url) # http://127.0.0.1:5000/home # 当前url的路径的上一级全部路径 print(request.url_root ) # http://127.0.0.1:5000/
request.json
前提是你得告诉是json数据
如果在请求中写入了 "application/json" 使用 request.json 则返回json解析数据, 否则返回 None
Flask中的jinja2和render_template
前端-普通数值
<table border="1px"> <thead> <tr> <td>姓名</td> <td>年龄</td> <td>性别</td> </tr> </thead> <tbody> <tr> <td>{{ stu.name }}</td> <td>{{ stu["age"] }}</td> <td>{{ stu.get("gender") }}</td> </tr> </tbody> </table>
效果
可以看出来,字典传入前端Jinja2 模板语言中的取值操作, 与Python中的Dict操作极为相似,并且多了一个student.name的对象操作
前端-【列表】
<table border="1px"> <thead> <tr> <td>姓名</td> <td>年龄</td> <td>性别</td> </tr> </thead> <tbody> {% for stu in stu_list %} <tr> <td>{{ stu.name }}</td> <td>{{ stu["age"] }}</td> <td>{{ stu.get("gender") }}</td> </tr> {% endfor %} </tbody> </table>
效果
前端-【字典】
<table border="1px"> <thead> <tr> <td>姓名</td> <td>年龄</td> <td>性别</td> </tr> </thead> <tbody> {% for item in stu_dict %} <tr> <td>{{ stu_dict[item].name }}</td> <td>{{ stu_dict[item]["age"] }}</td> <td>{{ stu_dict[item].get("gender") }}</td> </tr> {% endfor %} </tbody> </table>
效果
render_template中可传递多个关键字
利用 **{}字典的方式实现
py文件
@app.route("/allstudent") def all_student(): return render_template("all_student.html", **{"student":STUDENT , "student_list" : STUDENT_LIST, "student_dict": STUDENT_DICT})
jinja2 的高阶用法
后端文件
from flask import Flask from flask import render_template from flask import Markup # 导入 flask 中的 Markup 模块 app = Flask(__name__) @app.route("/") def index(): tag = "<input type='text' name='user' value='DragonFire'>" markup_tag = Markup(tag) # Markup帮助咱们在HTML的标签上做了一层封装,让Jinja2模板语言知道这是一个安全的HTML标签 print(markup_tag, type(markup_tag)) # <input type='text' name='user' value='DragonFire'> <class 'markupsafe.Markup'> return render_template("index.html", tag=markup_tag) app.run("0.0.0.0", 5000, debug=True)
还有一种方式就是在前端,加上 safe
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{ tag | safe}} <!-- 加上个 \ 管道符,然后 safe --> </body> </html>
jinja2 模板中执行函数
后端
def a_b_sum(a,b): return a + b @app.route("/home",methods=["GET","POST"]) def home(): return render_template("home.html",tag = a_b_sum)
前端
{{ tag }} <br> {{ tag(10,20) }}
效果
补充:定义全局函数,无需后端传递给前端,jinja2就可以直接执行的函数
后端
@app.template_global() # 定义全局模板函数 def a_b_sum(a,b): return a + b @app.template_filter() # 定义全局模板函数 def a_b_c_sum(a,b,c): return a + b + c @app.route("/home",methods=["GET","POST"]) def home(): return render_template("home.html")
前端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{ a_b_sum(99,1) }} <br> {{ 1 | a_b_c_sum(197,2) }} </body> </html>
jinja2 模板复用block
如果我们前端页面有大量重复页面,没必要每次都写,可以使用模板复用的方式复用模板
同理于django的母版
jinja2 模板语言中的宏定义
前端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h2>定义宏</h2> {% macro type_text(name,type) %} <input type="{{ type }}" name="{{ name }}" value="{{ name }}"> {% endmacro %} <br> <h2>使用宏来生成input标签</h2> {{ type_text("one","text") }} {{ type_text("two","text") }} </body> </html>
效果:
Flask 第五篇幅
flask-login与验证校验,待更新
https://www.cnblogs.com/minsons/p/8045916.html
Flask 的路由系统
route 装饰器中的参数
methods,当前url地址,允许访问的请求方式
@app.route("/index",methods=["GET","POST"]) # 当前url地址允许访问的请求方式 def index(): return render_template("index.html")
endpoint,反向url地址,默认为视图函数名(url_for)
from flask import Flask,render_template,url_for app = Flask(__name__) @app.route("/index",methods=["POST","GET"],endpoint="url_info") # 反向url地址,默认为视图函数名 (url_for) def index(): print(url_for("url_info")) # /index return render_template("index.html") app.run("0.0.0.0",9527,debug=True)
defaults,视图函数的参数默认值
from flask import Flask,render_template app = Flask(__name__) @app.route("/index",defaults={"user_list":["lmj","cly"]}) def index(user_list): return render_template("index.html",user_list=user_list) # 视图函数的默认参数 app.run("0.0.0.0",9527,debug=True)
strict_slashes,url地址结尾符"/"的控制,默认为True(结尾必须不能是"/")
from flask import Flask,render_template app = Flask(__name__) @app.route("/index",strict_slashes=False) # 有效访问地址:/index 或 /index/ def index(): return render_template("index.html") app.run("0.0.0.0",9527,debug=True)
redirect_to,url地址重定向
from flask import Flask,render_template app = Flask(__name__) @app.route("/home") def home(): return "你已跳转至home页面" @app.route("/index",redirect_to='/home') def index(): return render_template("index.html") app.run("0.0.0.0",9527,debug=True)
subdomain,子域名前缀subdomain="mjlee"这样写就可以得到mjlee.dream.com
前提是app.config["SERVER_NAME"]="dream.com"
from flask import Flask,render_template app = Flask(__name__) app.config["SERVER_NAME"] = "dream.com" @app.route("/index",subdomain="mjlee") def index(): return render_template("index.html") app.run("0.0.0.0",9527,debug=True) # 访问地址为:mjlee.dream.com/index
动态参数路由
from flask import Flask,url_for app = Flask(__name__) # 访问地址 http://127.0.0.1:5500/index/9527 @app.route("/index/<int:nid>",endpoint="url_info") def index(nid): print(url_for("url_info",nid=nid)) # /index/9527 return f"success get by {nid}" # success get by 9527 app.run("0.0.0.0",5500,debug=True)
<int:nid>就是在url后定义一个参数接收
但是这种动态参数路由,在url_for的时候,一定要将动态参数名+参数值添加进去(nid=nid),否则报错
补充:
另外还可使用正则路由,前提是正则玩的溜
Flask 的config
Flask的灵活体现出自其config配置,首先展示一下:
from flask import Flask app = Flask(__name__) # type:Flask print(app.config) print(app.config["APPLICATION_ROOT"]) # 默认情况下,config的28个key的详情: { 'DEBUG': False, # 是否开启DEBUG模式 'TESTING': False, # 是否开启测试模式 'PROPAGATE_EXCEPTIONS': None, # 异常传播(是否在控制台打印LOG) 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SECRET_KEY': None, # 启用Session的时候,一定要使用它 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), # days,Session的生命周期默认31天 'USE_X_SENDFILE': False, # 是否启用 x_sendfile 'LOGGER_NAME': '__main__', # 日志记录器的名称 'LOGGER_HANDLER_POLICY': 'always', 'SERVER_NAME': None, # 服务器访问域名 'APPLICATION_ROOT': None, # 项目的完整路径 'SESSION_COOKIE_NAME': 'session', # 在cookies中存放session加密字符串的名字 'SESSION_COOKIE_DOMAIN': None, # 在哪个域名下会产生session记录在cookies中 'SESSION_COOKIE_PATH': None, # cookie的路径 'SESSION_COOKIE_HTTPONLY': True, # 控制 cookie 是否应被设置 httponly 的标志 'SESSION_COOKIE_SECURE': False, # 控制 cookie 是否应被设置安全标志 'SESSION_REFRESH_EACH_REQUEST': True, # 这个标志控制永久会话如何刷新 'MAX_CONTENT_LENGTH': None, # 如果设置为字节数, Flask会拒绝内容大于此值的请求进入并返回403状态码 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), # 12小时,默认缓存控制的最大期限 'TRAP_BAD_REQUEST_ERRORS': False, # 如果这个值被设置为 True ,Flask不会执行 HTTP 异常的错误处理,而是像对待其它异常一样, # 通过异常栈让它冒泡地抛出。这对于需要找出 HTTP 异常源头的可怕调试情形是有用的。 'TRAP_HTTP_EXCEPTIONS': False, # Werkzeug 处理请求中的特定数据的内部数据结构会抛出同样也是“错误的请求”异常的特殊的 key errors 。 # 同样地,为了保持一致,许多操作可以显式地抛出 BadRequest 异常。 # 因为在调试中,你希望准确地找出异常的原因,这个设置用于在这些情形下调试。 # 如果这个值被设置为 True ,你只会得到常规的回溯。 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', # 生成URL的时候,如果没有可用的 URL 模式,会使用这个值 'JSON_AS_ASCII': True, # 默认情况下 Flask 使用 ascii 编码来序列化对象。如果这个值被设置为 False , # Flask不会将其编码为 ASCII,并且按原样输出,返回它的 unicode 字符串。 # 比如 jsonfiy 会自动地采用 utf-8 来编码它然后才进行传输。 'JSON_SORT_KEYS': True, #默认情况下 Flask 按照 JSON 对象的键的顺序来序来序列化它。 # 这样做是为了确保键的顺序不会受到字典的哈希种子的影响,从而返回的值每次都是一致的,不会造成无用的额外 HTTP 缓存。 # 你可以通过修改这个配置的值来覆盖默认的操作。但这是不被推荐的做法因为这个默认的行为可能会给你在性能的代价上带来改善。 'JSONIFY_PRETTYPRINT_REGULAR': True, 'JSONIFY_MIMETYPE': 'application/json', 'TEMPLATES_AUTO_RELOAD': None }
app.config["DEBUG"] = True
只要代码发生改动,自动重启Flask程序(app.run)
在控制台打印的信息非常全面
修改配置的方式:
1、直接对app.config进行修改
app.config["DEBUG"]=True
2、使用类的方式导入
首先要有一个settings.py的文件
settings.py
class FlaskSetting: DEBUG = True SECRET_KEY = "lmj"
然后在Flask的启动文件中引用
from flask import Flask app = Flask(__name__) app.config.from_object("settings.FlaskSetting") @app.route("/index") def index(): return "success" app.run("0.0.0.0",9528)
这叫做类导入配置
以上是针对一个已经实例化的app进行配置
那么在Flask实例化的时候,传递的参数有哪些?
其实可以理解为对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 # 主模块所在的目录的绝对路径,默认项目目录
这里面,我们常用的参数有
static_folder = 'static', # 静态文件目录的路径 默认当前项目中的static目录 static_url_path = None, # 静态文件目录的url路径 默认不写是与static_folder同名,远程静态文件时复用 template_folder = 'templates' # template模板目录, 默认当前项目中的 templates 目录
Flask 的蓝图
将 功能 与 主服务 分开
客户管理系统:
查看客户(blueprint)
修改客户(blueprint)
添加客户(blueprint)
删除客户(blueprint)
第一个蓝图示例
目录结构
蓝图check_view.py中的内容
from flask import Blueprint cv = Blueprint("cv", __name__) @cv.route("/index") def index(): return "show page" @cv.route("/home") def home(): return "home page"
主服务 manage.py 中的内容
from flask import Flask from crm_views import add_view,check_view app = Flask(__name__) app.config["DEBUG"] = True app.register_blueprint(check_view.cv) app.register_blueprint(add_view.av) app.run("0.0.0.0",5500)
访问http://127.0.0.1:5500/home的效果
结论:没有在Flask对象中添加路由,但是注册了有路由和视图函数的蓝图对象。
如何理解蓝图
接下来看看,在示例话蓝图的时候可以传递的参数都有什么
目录结构
check_view.py
from flask import Blueprint,render_template cv = Blueprint("cv", __name__, template_folder="cv_templates", # 每个蓝图都可以独立出一套templates模版文件夹,若不写则默认共享项目根目录中的templates static_folder="cv_static" # 静态文件目录也是可以独立出来 ) @cv.route("/index") def index(): return render_template("cv_show.html") @cv.route("/home") def home(): return "home page"
cv_show.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>check view page</h2> <img src="/cv_static/lmj.png" alt="yanyan bf" style="height: 100px"> </body> </html>
http://127.0.0.1:5500/index访问效果
注意:蓝图内部的视图函数及route重复,则主服务则按照注册的顺序执行,先注册的则先执行!
蓝图制作增删改查
目录结构
student
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/8/30 上午10:30 # @Author : MJay_LEE # @File : __init__.py.py # @Contact : limengjiejj@hotmail.com from flask import Flask from student_select import stu_select from student_add import stu_add from student_edit import stu_edit from student_del import stu_del def create_app(): app = Flask(__name__) app.config["DEBUG"] = True app.register_blueprint(stu_select.ss) app.register_blueprint(stu_add.sa) app.register_blueprint(stu_edit.se) app.register_blueprint(stu_del.sd) return app
student_add
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加学生</title> </head> <body> <h2>添加学生</h2> <form action="" method="post"> <p><label for="id">id<input type="text" name="id"></label></p> <p><label for="name">name<input type="text" name="name"></label></p> <p><label for="age">age<input type="text" name="age"></label></p> <p><label for="gender">gender<input type="text" name="gender"></label></p> <p><input type="submit" value="添加学生"></p> </form> </body> </html>
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/8/30 上午11:03 # @Author : MJay_LEE # @File : stu_add.py # @Contact : limengjiejj@hotmail.com from flask import Blueprint,render_template,redirect,request from student_data import STUDENT sa = Blueprint("sa", __name__, template_folder="html" ) @sa.route("/s_add",methods=["GET","POST"]) def s_add(): if request.method == "POST": id = request.form.get("id") name = request.form.get("name") age = request.form.get("age") gender = request.form.get("gender") STUDENT.append({ "id":id, "name":name, "age":age, "gender":gender }) return redirect("/s_list") return render_template("s_add.html")
student_del
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/8/30 下午4:23 # @Author : MJay_LEE # @File : stu_del.py # @Contact : limengjiejj@hotmail.com from flask import Blueprint,redirect from student_data import STUDENT sd = Blueprint("sd",__name__) @sd.route("/s_del/<int:id>") def s_del(id): for key,stu in enumerate(STUDENT): if stu["id"] == id: STUDENT.pop(key) return redirect("/s_list")
student_edit
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加学生</title> </head> <body> <h2>学生修改</h2> <form action="" method="post"> <p><label for="id">id<input type="text" name="id" value="{{ stu.id }}"></label></p> <p><label for="name">name<input type="text" name="name" value="{{ stu.name }}"></label></p> <p><label for="age">age<input type="text" name="age" value="{{ stu.age }}"></label></p> <p><label for="gender">gender<input type="text" name="gender" value="{{ stu.gender }}"></label></p> <p><input type="submit" value="修改学生"></p> </form> </body> </html>
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/8/30 上午11:34 # @Author : MJay_LEE # @File : stu_edit.py # @Contact : limengjiejj@hotmail.com from flask import Blueprint,render_template,request,redirect from student_data import STUDENT se = Blueprint("se",__name__,template_folder="html") @se.route("/s_edit/<int:id>",methods=["GET","POST"]) def s_edit(id): if request.method == "POST": new_id = int(request.form.get("id")) new_name = request.form.get("name") new_age = request.form.get("age") new_gender = request.form.get("gender") stu_dict = { "id":new_id, "name":new_name, "age":new_age, "gender":new_gender } for stu in STUDENT: if stu["id"] == id: stu.update(stu_dict) return redirect("/s_list") for stu in STUDENT: if stu["id"] == id: return render_template("s_edit.html",stu=stu) return render_template("s_edit.html",stu="")
student_select
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/8/30 上午11:34 # @Author : MJay_LEE # @File : stu_edit.py # @Contact : limengjiejj@hotmail.com from flask import Blueprint,render_template,request,redirect from student_data import STUDENT se = Blueprint("se",__name__,template_folder="html") @se.route("/s_edit/<int:id>",methods=["GET","POST"]) def s_edit(id): if request.method == "POST": new_id = int(request.form.get("id")) new_name = request.form.get("name") new_age = request.form.get("age") new_gender = request.form.get("gender") stu_dict = { "id":new_id, "name":new_name, "age":new_age, "gender":new_gender } for stu in STUDENT: if stu["id"] == id: stu.update(stu_dict) return redirect("/s_list") for stu in STUDENT: if stu["id"] == id: return render_template("s_edit.html",stu=stu) return render_template("s_edit.html",stu="")
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/8/30 上午10:33 # @Author : MJay_LEE # @File : stu_select.py # @Contact : limengjiejj@hotmail.com from flask import Blueprint,render_template from student_data import STUDENT ss = Blueprint("ss", __name__, template_folder="html", ) @ss.route("/s_list") def s_list(): return render_template("s_list.html",stu_list=STUDENT)
manager.py
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/8/30 上午10:31 # @Author : MJay_LEE # @File : manager.py # @Contact : limengjiejj@hotmail.com from student import create_app flask_app = create_app() flask_app.run("0.0.0.0",9527)
student_data.py
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/8/30 上午10:31 # @Author : MJay_LEE # @File : student_data.py # @Contact : limengjiejj@hotmail.com STUDENT = [ {"id":1,"name":"lmj","age":18,"gender":"male"}, {"id":2,"name":"cly","age":23,"gender":"female"}, {"id":3,"name":"festival","age":1,"gender":"male"}, ]
before_request 与 after_request
现在模拟一个简单的场景
一个Flask程序,有4个路由和视图函数,做登录校验
如果登录了,就可以访问index和home页面
若没有登录就跳转到login登录
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/8/31 上午10:45 # @Author : MJay_LEE # @File : main.py # @Contact : limengjiejj@hotmail.com from flask import Flask,request,redirect,session,render_template app = Flask(__name__) app.secret_key = "limengjie" # 在请求(request)之前作出响应 @app.before_request def is_login(): if request.path == "/login": return None if not session.get("user"): return redirect("/login") # 在响应(response)之前作出响应 @app.after_request def foot_log(environ): if request.path != "/login": print("有访客访问了",request.path) return environ @app.route("/login",methods=["GET","POST"]) def login(): if request.method == "POST": user = request.form.get("user") if user == "lmj": session["user"] = 1 return redirect("/index") return render_template("login.html") @app.route("/index") def index(): return "Login successs" @app.route("/home") def home(): return "Home" @app.route("/logout",methods=["GET","POST"]) def logout(): if request.method == "POST": session["user"] = None return "注销成功" return render_template("logout.html") app.run("0.0.0.0",9527,debug=True)
注意:session一定要配合secret_key一起使用
理论引导实践,欲求精通还需多加刻苦实践!祝君好运!
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:python进程-进阶
下一篇:Python IF 条件判断
- Flask request接口获取参数 2019-08-13
- Flask的上下文管理 2019-07-24
- Flask学习之旅--数据库 2019-07-24
- 基于flask的网页聊天室(二) 2019-05-13
- 基于flask的网页聊天室(三) 2019-05-13
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash