Flask攻略
python三大框架预览
代码语言:javascript复制Python Web框架分类
功能分类:
a:收发消息相关(socket)
b:根据不同的URL执行不同的函数(业务逻辑相关的)
c:实现动态网页(字符串的替换)
Web框架分类:
1、自己实现b,c,使用第三方的a(Django)
2、自己实现b,使用第三方的a,c(Flask)
3、自己实现abc(Tornado)
两个模块
web服务器程序 《---WSGI协议---》 web应用程序
1、wsgiref
Django开发环境使用的就是wsgiref模块
2、jinja2(Flask)
渲染HTML页面,其实就是实现字符串的替换
代码语言:javascript复制python三大框架优缺点
Flask:
优点: 小而精,短小精悍,第三方组件特别多
缺点: 组件更新速度取决于开源者
Tornado:
优点: 原生的WebSocket, 异步任务, IO非阻塞玩
缺点: 没有组件,Session都没有
Django:
优点: 大而全,组件非常全面
缺点: 太大,重量级框架,加载太大,浪费资源
Flask的优势
代码语言:javascript复制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原理
代码语言:javascript复制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三剑客
代码语言:javascript复制# HTTPresponse: return "Hello Flask"
# render_template: return render_template("login.html") #templates
# redirect: return redirect("/login")
示例:
代码语言:javascript复制# 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需要自己开启:(流程如下)
代码语言:javascript复制from flask import Flask, render_template, redirect
app = Flask(__name__)
app.run() # 可以自定义ip 端口 和debug模式
Flask的request
代码语言:javascript复制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的模板语言
代码语言:javascript复制# 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
代码语言:javascript复制{{ input | safe }}
Markup() : Markup("<input type='text' name='input_tag'>")
pycharm识别模板语言的格式:设置jinja2的语言
Session
secret_key = "" 这个是开启session必备的参数
代码语言:javascript复制form flask import session
app.secret_key = "随意"
session["user"] = "xxxx"
if session.get("user")
Jsonify
json的转换兼容性比json模块强
代码语言:javascript复制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路由
代码语言:javascript复制flk.route()
"/index" 路由地址
"/index/<nid>" 动态路由地址(视图函数需要nid参数)
"/index/<int:nid>" 动态路由地址
"/files/<filename>" <> 里面的filename可以是本地文件内的任何一个文件全名,可以把任意存在的文件内容打印到页面上
代码语言:javascript复制# 可以把所有文件内容显示到页面上面
@flk.route('/files/<filename>')
def files(filename):
return send_file(filename)
补充
代码语言:javascript复制methods=["GET","POST"] 允许URL的请求方式
endpoint="index" 反向URL操作,可以解决Inner重名的问题
redirect_to="/index2" 服务器端页面跳转 301永久性重定向
strict_slashes=False 可以使用"/"结尾 反之不可以
defaults={"nid":1} 视图函数默认参数
Flask配置
settings.FlaskSettings
代码语言:javascript复制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,
}
flask的整套配置项
蓝图(Blueprint)
代码语言:javascript复制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对象,具备独立模板和静态目录
代码语言:javascript复制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 在第一次请求进入视图函数之前做出的处理
代码语言:javascript复制# 类似于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
代码语言:javascript复制#!/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,在我们看来其实就是直接返回字符串
代码语言:javascript复制from flask import Flask
app = Flask(__name__)
@app.route('/') # 路由
def index(): # 视图
return "Hello Flask" # HTTPResponse
Flask中的redirect
代码语言:javascript复制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)
代码语言:javascript复制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文件
代码语言:javascript复制<form action="" method="post" novalidate>
<input type="text" name="user" id="">
<input type="password" name="pwd" id="">
<input type="submit" value="提交">
py文件
代码语言:javascript复制@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文件
代码语言:javascript复制<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文件
代码语言:javascript复制@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页面
结果
代码语言:javascript复制===================request.args===================
['id', 'age']
==================request.values==================
['id', 'age', 'pwd', 'user']
==============request.values.to_dict==============
{'user': 'lmj', 'pwd': '123', 'id': '1', 'age': '18'}
注意:
代码语言:javascript复制# 注意这里的坑来啦! 坑来啦!
# 如果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
代码语言:javascript复制print(request.cookies)
"""
{
'csrftoken': 'elPT8HW8Zw74NPSftY0suJEqbm3cOxEPl05f1oezHN61kikgqOgcuXWtiJCyhtuX',
'sessionid': 'cqfjxs0svrq2nqf9i4hdghdvqep6468w'
}
"""
request.headers,请求头中的参数
代码语言:javascript复制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同样可以拿到里面的数据
代码语言:javascript复制你一定要知道 request 是基于 mimetype 进行处理的
mimetype的类型 以及 字符串儿 : http://www.w3school.com.cn/media/media_mimeref.asp
如果不属于上述类型的描述,request就会将无法处理的参数转为Json存入到 data 中
request.files,文件上传
遇到文件上传,request.files村的就是上传的文件,但Flask在这个文件的操作中加了封装
html文件
代码语言:javascript复制<form action="" method="post" enctype="multipart/form-data" novalidate>
<input type="file" name="file">
<input type="submit" value="提交">
</form>
py文件
代码语言:javascript复制@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的路径获取
代码语言:javascript复制 # 获取当前的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数据
代码语言:javascript复制如果在请求中写入了 "application/json" 使用 request.json 则返回json解析数据, 否则返回 None
Flask中的jinja2和render_template
前端-普通数值
代码语言:javascript复制<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的对象操作
前端-【列表】
代码语言:javascript复制<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>
效果
前端-【字典】
代码语言:javascript复制<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文件
代码语言:javascript复制@app.route("/allstudent")
def all_student():
return render_template("all_student.html", **{"student":STUDENT ,
"student_list" : STUDENT_LIST,
"student_dict": STUDENT_DICT})
jinja2 的高阶用法
后端文件
代码语言:javascript复制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
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ tag | safe}} <!-- 加上个 管道符,然后 safe -->
</body>
</html>
jinja2 模板中执行函数
后端
代码语言:javascript复制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)
前端
代码语言:javascript复制{{ tag }}
<br>
{{ tag(10,20) }}
效果
补充:定义全局函数,无需后端传递给前端,jinja2就可以直接执行的函数
后端
代码语言:javascript复制@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")
前端
代码语言:javascript复制<!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 模板语言中的宏定义
前端
代码语言:javascript复制<!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与验证校验,待更新
代码语言:javascript复制https://www.cnblogs.com/minsons/p/8045916.html
参考笔记
Flask 的路由系统
route 装饰器中的参数
methods,当前url地址,允许访问的请求方式
代码语言:javascript复制@app.route("/index",methods=["GET","POST"]) # 当前url地址允许访问的请求方式
def index():
return render_template("index.html")
endpoint,反向url地址,默认为视图函数名(url_for)
代码语言:javascript复制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,视图函数的参数默认值
代码语言:javascript复制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(结尾必须不能是"/")
代码语言:javascript复制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地址重定向
代码语言:javascript复制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"
代码语言:javascript复制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
动态参数路由
代码语言:javascript复制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配置,首先展示一下:
代码语言:javascript复制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进行修改
代码语言:javascript复制app.config["DEBUG"]=True
2、使用类的方式导入
首先要有一个settings.py的文件
settings.py
代码语言:javascript复制class FlaskSetting:
DEBUG = True
SECRET_KEY = "lmj"
然后在Flask的启动文件中引用
代码语言:javascript复制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实例进行的初始配置,如下:
代码语言:javascript复制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 # 主模块所在的目录的绝对路径,默认项目目录
这里面,我们常用的参数有
代码语言:javascript复制static_folder = 'static', # 静态文件目录的路径 默认当前项目中的static目录
static_url_path = None, # 静态文件目录的url路径 默认不写是与static_folder同名,远程静态文件时复用
template_folder = 'templates' # template模板目录, 默认当前项目中的 templates 目录
Flask 的蓝图
(老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)
(老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)
(老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)
(老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)
(老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)
(老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)
(老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)
(老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)