ディレクトリ
まず、知人フラスコ
1.1フラスコは何ですか?
このフラスコは、2010年4月1日が、その後人気のエイプリルフールのジョークで著者アーミンRonacherであるため、正式なPythonで書かれたWebフレームワークになります
フラスコは、私たちがいることを大規模かつ包括的なWebフレームワークをジャンゴ、それとDjangoの絆との違いについて話を最初に導入のフラスコ前に、すぐにWebサイトやWebサービスを実装するために使用できるようにマイクロのPython、Python言語で書かれたWebフレームワークであります多くのビルトインモジュール、フラスコは、小さいながらも優れた軽量なフレームワークであり、Djangoは大規模で包括的な機能、フラスコは、開発者がアプリケーションを選択する前にそれを開発していない可能、基本構成のみ、ワンストップソリューションジャンゴのアイデアが含まれていますこれは、インフラストラクチャに多くの時間を費やしています。そこDjangoのテンプレート、フォーム、ルーティング、基本的なデータベース管理などの組み込み機能。これとは対照的に、ただカーネルフラスコは、デフォルトでは2つの外部のライブラリに依存している:Jinja2のテンプレートエンジンとWSGIツールセット--Werkzeug、フラスコの使用のすべてのツールの基本的な機能は、フラスコの予約を展開する輸入の形に依存されコアな機能のWeb開発。
WSGI(Webサーバゲートウェイインターフェース)はPythonのWebサーバーがどのようにPythonのWebサーバー、本質的にソケット・サーバと標準のPython Webプログラムと通信する方法を指定するために使用されます。そしてWERKZEUG WSGIモジュールは、特定の実装です
キーワード:Pythonで書かれたマイクロWebフレームワークと2つのコアライブラリ(Jinja2のテンプレートエンジンとWSGIツールセット)
1.2なぜフラスコべきでしょうか?
実質的に性能要件は、一般的なWeb開発をフラスコ、および他のWebフレームに優れた柔軟性と拡張性、各種データベースのためのフィット感が非常に高い会います
キーワード:1 2パフォーマンスは基本的に需要の柔軟性と強力な拡張性を満たすデータベースの様々なフィット3に高いです。
実際の運用環境で4、高速で小さなプロジェクトの開発、大規模なプロジェクトの柔軟な設計
二、フラスコクイックスタート
'''
pip install flask
'''
# 1 导入flask,我们要用flask,就必须导入Flask
from flask import Flask
# 2 生成一个Flask对象,__name__表示当前文件的名字
app = Flask(__name__)
# 3 添加路由,flask用的是装饰器的模式
#注册路由,并写响应函数index
@app.route("/")
def index():
return "Hello flask"
if __name__ == '__main__':
#4 启动flask
#run里面是执行了run_simple(host,port,self=app,也就是flask对象)
app.run()
三、フラスコ4人の剣士
'''
响应字符串
响应html页面
跳转页面
返回json字符串
'''
from flask import Flask, render_template, redirect, jsonify
app = Flask(__name__)
@app.route("/index")
def index():
# 1.返回字符串
# return "hello word 啊啊啊"
# 2.返回html页面
# 返回html,从flask里面导入render_template
# return render_template("index.html")
# 3.跳转路由
# return redirect('/login')
# 4.返回数据转json返回,从flask中导入jsonify
# data = {"name": "jeff", "age": "18"}
# return jsonify(data)
pass
@app.route("/login")
def login():
return "我是login页面"
if __name__ == '__main__':
app.run()
三、フラスコのプロフィール
'''
四种配置flask方法配置
1.直接给app对象赋值属性
2.以字典的形式,给flask配置文件做配置
3.以文件的形式给flask做配置(django就是这种)
4.以类的形式,给flask做配置(推荐使用)
'''
from flask import Flask
app = Flask(__name__)
# 方式1(不推荐),因为只能配置两项。debug和secret_key
# app.debug = True # 默认false,自动重启
# 方式2 字典的形式
# app.config["DEBUG"] = True
# 方式3 以文件的形式,在from_pyfile里传递路径
# app.config.from_pyfile("settings.py")
# 方式4 以类的形式,一个文件多个套配置,减少测试与更改(推荐使用)
# app.config.from_object("setobj.settings")
@app.route("/")
def index():
return "json 是炮王"
if __name__ == '__main__':
app.run()
三つの方法のプロフィール:
同様に、Djangoのような、特別な設定ファイル
DEBUG = True
4つの方法の設定クラス:
長所:ファイル、設定の複数のセット。異なる構成の異なるクラス、構成が変更されるべき項目を低減オンラインテスト
class settings():
DEBUG = True
あなたは、プロパティを設定することができます
flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:
'''
default_config = ImmutableDict(
{
"ENV": None,
"DEBUG": None,
"TESTING": False,
"PROPAGATE_EXCEPTIONS": None,
"PRESERVE_CONTEXT_ON_EXCEPTION": None,
"SECRET_KEY": None,
"PERMANENT_SESSION_LIFETIME": timedelta(days=31),
"USE_X_SENDFILE": False,
"SERVER_NAME": None,
"APPLICATION_ROOT": "/",
"SESSION_COOKIE_NAME": "session",
"SESSION_COOKIE_DOMAIN": None,
"SESSION_COOKIE_PATH": None,
"SESSION_COOKIE_HTTPONLY": True,
"SESSION_COOKIE_SECURE": False,
"SESSION_COOKIE_SAMESITE": None,
"SESSION_REFRESH_EACH_REQUEST": True,
"MAX_CONTENT_LENGTH": None,
"SEND_FILE_MAX_AGE_DEFAULT": timedelta(hours=12),
"TRAP_BAD_REQUEST_ERRORS": None,
"TRAP_HTTP_EXCEPTIONS": False,
"EXPLAIN_TEMPLATE_LOADING": False,
"PREFERRED_URL_SCHEME": "http",
"JSON_AS_ASCII": True,
"JSON_SORT_KEYS": True,
"JSONIFY_PRETTYPRINT_REGULAR": False,
"JSONIFY_MIMETYPE": "application/json",
"TEMPLATES_AUTO_RELOAD": None,
"MAX_COOKIE_SIZE": 4093,
}
)
'''
四つ、フラスコ経路
4.1ソースコード解析
# 源码分析:
'''
self.add_url_rule(rule, endpoint, f, **options)
def add_url_rule(
self, # app对象
rule, # url路由
endpoint=None, # 路由别名
view_func=None, # 响应的函数名
provide_automatic_options=None,
**options
):
methods :['POST','GET'] —》控制请求方法,不传默认只能GET方法
'''
# @app.route的本质就在执行add_url_rule
# rule是路由,endpoint是路由别名,view_func是响应函数
# 如果endpoint不传就是响应的函数名
4.2 1:某
from flask import Flask , url_for, redirect
app = Flask(__name__)
def index():
print()
return "我是index"
# @app.route('/detail/<int:nid>',methods=['GET','POST'],endpoint='detail') # 典型写法
@app.route('/login')
def login():
print(url_for("index1")) # 走的别名,如果别名没有写,默认函数名
return redirect(url_for("index1")) # 走的别名,如果别名没有写,默认函数名
# url_for:
# 用endpoint获取路由要用url_for 在flask中导入,也就是反向解析
# 路由
app.add_url_rule('/', endpoint='index1', view_func=index)
# endpoint 别名
# view_func 响应的函数名
if __name__ == '__main__':
app.run()
4.3 2:有名なグループ化
from flask import Flask , url_for, redirect
app = Flask(__name__)
# 必须接收分组名字一样的 nid
def index(nid):
print(nid)
return "我是index"
# 路由:有名分组
app.add_url_rule('/index/<string:nid>', endpoint='index1', view_func=index, methods=['POST','GET'])
app.add_url_rule('/index/<int:nid>', endpoint='index', view_func=index, methods=['POST','GET'])
# 浏览器:http://127.0.0.1:5000/index/asdfas
# string、int 规定接收的类型
if __name__ == '__main__':
app.run()
4.4ルーティング小さな概要
总结:
1 @app.route("/login") 的本质app.add_url_rule("/login",view_func=login),所以我们就可以用这两个方式来添加路由
2 路由的参数,
2.1 endpoint,做是反向解析,如果上面添加路由的时候,没有传递endpoint就是使用响应函数的函数名,反向解析用url_for(),做解析,这个url_for必须在flask里面导入
2.2 methods=["POST","GET"],该参数控制路由允许哪些请求方法访问,如果不传,默认只能GET方法
2.3 路由以及路由路由转化器。"/index/<int:nid>",<参数的类型:用哪个变量来接收>,响应函数中的形参的名字必须转化器中一致。
4.5デフォルトコンバータ
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
4.6カスタム・コンバータ
#1 写类,继承BaseConverter
#2 注册:app.url_map.converters['regex'] = RegexConverter
# 3 使用:@app.route('/index/<regex("\d+"):nid>') 正则表达式会当作第二个参数传递到类中
from flask import Flask, views, url_for
from werkzeug.routing import BaseConverter
app = Flask(import_name=__name__)
# 1.写类
class RegexConverter(BaseConverter):
"""
自定义URL匹配正则表达式
"""
def __init__(self, map, regex):
super(RegexConverter, self).__init__(map)
self.regex = regex
def to_python(self, value):
"""
路由匹配时,匹配成功后传递给视图函数中参数的值
"""
return int(value)
def to_url(self, value):
"""
使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
"""
val = super(RegexConverter, self).to_url(value)
return val
# 2.注册:添加到flask中
app.url_map.converters['regex'] = RegexConverter
# 正则匹配处理结果,要交给to_python,to_python函数可以对匹配处理结果做处理
# 3.使用:
@app.route('/index/<regex("\d+"):nid>')
def index(nid):
print(url_for('index', nid='888'))
return 'Index'
if __name__ == '__main__':
app.run()
4.7カスタム・コンバータの概要
1 导入from werkzeug.routing import BaseConverter
2 我写个继承BaseConverter。实现3个方法,def __init__ , def to_python , def to_url
3 将上面的类注册到app.url_map.converters['regex'] = RegexConverter中
4 然后就可以在路由转化器中使用3中的regex("传正则")
5 当路由被访问以后。regex("传正则")会匹配结果,把结果传递to_python,我们可以进行再次处理,to_python处理好的结果,会传递给响应函数的形参
6 当用url做反向解析的时候,传递给路由转化器的参数,会经过to_url,进行处理。处理以后,在拼接到路由。
五、フラスコテンプレートレンダリング
PYファイル:
from flask import Flask,render_template,Markup
app = Flask(__name__)
app.debug = True
USERS = {
1:{'name':'张三','age':18,'gender':'男','text':"道路千万条"},
2:{'name':'李四','age':28,'gender':'男','text':"安全第一条"},
3:{'name':'王五','age':18,'gender':'女','text':"行车不规范"},
}
def func1(arg,tank):
return Markup(f"<h1>饼哥正帅,{arg} is sb {tank} is same as {arg}</h1>")
@app.route("/")
def index():
# data = {
# "user" :USERS,
# "name": "jason"
# }
return render_template("index.html",user = USERS,name="jason",ht1 = func1,ht="<h1>饼哥正帅</h1>")
#return render_template("index.html",**data)
if __name__ == '__main__':
app.run()
1.ループ変数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1> 我是html</h1>
<table>
{% for k,v in user.items() %}
<tr>
<td>{{ k }}</td>
<td>{{ v.name }}</td>
<td>{{ v['name'] }}</td>
<td>{{ v.get('name') }}</td>
<td>{{url_for("index")}}</td>
</tr>
{% endfor %}
</body>
</html>
2.解析ロジック
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户列表</h1>
<table>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}
</table>
</body>
</html>
3.機能の実行、パラメータを渡します
ブラケットを行うことができるよりジャンゴ機能、送信パラメータ
from flask import Flask,render_template,Markup
app = Flask(__name__)
app.debug = True
def func1(arg,tank):
return Markup(f"<h1>饼哥正帅,{arg} is sb {tank} is same as {arg}</h1>")
@app.route("/")
def index():
# data = {
# "user" :USERS,
# "name": "jason"
# }
return render_template("index.html",ht1 = func1,ht="<h1>饼哥正帅</h1>")
if __name__ == '__main__':
app.run()
htmlファイル
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ ht|safe}}
{{ht1("jaosn","tank")}} // 传参数
</body>
</html>
六、フラスコ要求と応答
from flask import Flask, request, make_response
app = Flask(__name__)
app.debug = True
@app.route('/', methods=['POST', 'GET'])
def index():
# print('请求方法',request.method) # 请求方法
# print('get请求的参数',request.args) # get 请求的参数
# print('post请求的参数',request.form) # post请求的参数
# print('请求的cookies',request.cookies) # 请求的cookies
# print('post与get的所有参数',request.values) # post与get的所有参数
# 响应头,添加make_response
response = make_response('ok')
#response = make_response(render_template("login.html"))
# 设置cookie
response.set_cookie("key","val")
return 'OK'
if __name__ == '__main__':
app.run()
関連情報を求めます
请求相关的信息
print("请求方法",request.method)#请求方法
print("get请求的参数",request.args)# get请求的参数
print("post请求的参数",request.form) #post请求的参数
print("post,与get的所有参数",request.values)#post,与get的所有参数
print("请求的cookies",request.cookies)#请求的cookies
请求相关信息
request.method 提交的方法
request.args get请求提及的数据
request.form post请求提交的数据
request.values post和get提交的数据总和
request.cookies 客户端所带的cookie
request.headers 请求头
request.path 不带域名,请求路径
request.full_path 不带域名,带参数的请求路径
request.script_root
request.url 带域名带参数的请求路径
request.base_url 带域名请求路径
request.url_root 域名
request.host_url 域名
request.host 127.0.0.1:500
セブン、クッキーを設定します
from flask import Flask, make_response
app = Flask(__name__)
app.debug = True
@app.route('/', methods=['POST', 'GET'])
def index():
# 响应头,添加make_response
response = make_response('ok')
# 设置cookies
response.set_cookie('key', 'val')
# 删除cookies
response.delete_cookie("key")
# 设置响应头
response.headers["x-somexx"] = "A SB"
return response
if __name__ == '__main__':
app.run()
クッキーのパラメータを設定
key, 键
value='', 值
max_age=None, 超时时间 cookie需要延续的时间(以秒为单位)如果参数是\ None`` ,这个cookie会延续到浏览器关闭为止
expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问,浏览器只会把cookie回传给带有该路径的页面,这样可以避免将cookie传给站点中的其他的应用。
domain=None, Cookie生效的域名 你可用这个参数来构造一个跨站cookie。如, domain=".example.com"所构造的cookie对下面这些站点都是可读的:www.example.com 、 www2.example.com 和an.other.sub.domain.example.com 。如果该参数设置为 None ,cookie只能由设置它的站点读取
secure=False, 浏览器将通过HTTPS来回传cookie
httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
八、セッションのフラスコ
クッキー:キーはクライアントに保存され
たセッション:クライアントのキーと値のペアに格納されている
アルゴリズムによってチェックするために、クライアントに保存されたトークン
8.1設定セッション(バージョンを使用して)
これで、セッションキーの前の使用について設定する必要があります。
app.secret_key="asdas" # 值随便
# app.config['SECRET_KEY'] = os.urandom(24) # 配置session使用的秘钥
设置:session['username'] = 'xxx'
# 在django中发什么三件事,1,生成一个随机的字符串 2 往数据库存 3 写入cookie返回浏览器
# 在flask中他没有数据库,但session是怎样实现的?
# 生成一个密钥写入这个cookie,然后下次请求的时候,通过这个cookie解密,然后赋值给session
# 我们通过app.session_interface来查看
删除:session.pop('username', None)
フラスコのセッションオブジェクトは、Cookieの暗号化のためのストレージを提供し、セッションデータは、秘密鍵データによって署名暗号化されています。
from flask import Flask, session
import os
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24) # 配置session使用的秘钥
@app.route('/')
def set_session_info():
session['username'] = 'mark' # 使用用户信息配置sesion信息作为cookie,并添加到响应体中
return '设置session信息'
辞書のようなセッション・オブジェクトが動作することができ、内部辞書は、情報を暗号化することで応答を自動的にブラウザに返されるときに、クッキーなどの身体の適切な操作に加えられます。
session['username'] = 'mark'
session['userphone'] = '123456' # 可以指定多条session信息,统一放到响应的cookie中返回给浏览器
8.2設定セッション(解析版)
from flask import Flask,session
app = Flask(__name__)
# 要用session,必须app配置一个密钥
app.secret_key = "asdasdihasdiuh"
# 设置session的名字,默认配置文件中为:session
app.config['SESSION_COOKIE_NAME']="python13session"
# app.session_interface
#app.session_interface实现了两个方法,一个叫save_session,一个open_session,
# save_session 存session执行,加密设置cookies
# open_session 取session执行,解密大字典,拿到session
@app.route("/",)
def index():
#如何设置sessoion
# 1 导入session
# 2 给sessoion设置值
session['name'] = "egon"
return "ok"
@app.route("/login")
def login():
print(session["name"])
return "login"
if __name__ == '__main__':
app.run()
8.3セッションを設定することは有効です
后端Flask跟浏览器交互默认情况下,session cookie会在用户关闭浏览器时清除。通过将session.permanent属性设为True可以将session的有效期延长为31天,也可以通过操作app的配置PERMANENT_SESSION_LIFETIME来设置session过期时间。
案例 3.3.2.1:开启指定session过期时间模式
from flask import Flask, session
import os
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)
@app.route('/')
def set_session_info():
session['username'] = 'mark'
session['userphone'] = '123456'
session.permanent = True # 开启设置有效期,默认为31天后过期
return 'Hello World!'
...
セットカスタム有効期限
# 通过设置PERMANENT_SESSION_LIFETIME指定具体的过期时间
from datetime import timedelta
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=1) # 设置为1小时候过期
8.4取得のsessoin
フラスコは、セッションオブジェクトを介して取得したセッション情報に設定されます、オブジェクトは、セッション辞書クラスを継承するので、辞書の取得値が方法である場合。その内部ブラウザでは、メッセージ解読セッション上を通過します。
@app.route('/get_session/')
def get_session():
username = session.get('username')
userphone = session.get('userphone')
if username or userphone:
return "{},{}".format(username, userphone)
return "session为空"
8.5削除セッション
session
オブジェクトの呼び出しpop()
特定に応じては、session
指定されたセッション情報のキーを削除しました。
セッションオブジェクトの呼び出しは、clear()
このドメイン名に関するすべてこのブラウザセッション要求情報をクリアすることができます
@app.route('/del_session/')
def del_session():
session.pop('username')
# session.clear()
return '删除成功'
8.6ソースコード解析
セッションソース実装プロセス
-save_seesion
-响应的时候,把session中的值加密序列化放大到了cookie中,返回到浏览器中
-open_session
-请求来了,从cookie中取出值,反解,生成session对象,以后再视图函数中直接用sessoin就可以了。
ソースコード解析
# app.session_interface 点进去
class SecureCookieSessionInterface(SessionInterface):
salt = "cookie-session"
digest_method = staticmethod(hashlib.sha1)
key_derivation = "hmac"
serializer = session_json_serializer
session_class = SecureCookieSession
def get_signing_serializer(self, app):
if not app.secret_key:
return None
signer_kwargs = dict(
key_derivation=self.key_derivation, digest_method=self.digest_method
)
return URLSafeTimedSerializer(
app.secret_key,
salt=self.salt,
serializer=self.serializer,
signer_kwargs=signer_kwargs,
)
# 取session的时候执行的
def open_session(self, app, request):
s = self.get_signing_serializer(app)
if s is None:
return None
##cookie键是SESSION_COOKIE_NAME"=session
val = request.cookies.get(app.session_cookie_name)
print("open_session.session_cookie_name,", app.session_cookie_name, )
if not val:
return self.session_class()
max_age = total_seconds(app.permanent_session_lifetime)
try:
data = s.loads(val, max_age=max_age)
print("self.session_class(data)", self.session_class(data) )
return self.session_class(data)
except BadSignature:
return self.session_class()
#存session的时候执行的
def save_session(self, app, session, response):
domain = self.get_cookie_domain(app)
path = self.get_cookie_path(app)
# If the session is modified to be empty, remove the cookie.
# If the session is empty, return without setting the cookie.
if not session:
if session.modified:
response.delete_cookie(
app.session_cookie_name, domain=domain, path=path
)
return
# Add a "Vary: Cookie" header if the session was accessed at all.
if session.accessed:
response.vary.add("Cookie")
if not self.should_set_cookie(app, session):
return
httponly = self.get_cookie_httponly(app)
secure = self.get_cookie_secure(app)
samesite = self.get_cookie_samesite(app)
expires = self.get_expiration_time(app, session)
# 把session做了一个加密,把整个session的key--》val,全部加密,的到一个value值,
#session是一个大字典,
val = self.get_signing_serializer(app).dumps(dict(session))
# 他把session加密后得到的val存到cookie里面了
#cookie键是SESSION_COOKIE_NAME"=session
print("源码中的session",dict(session))
print("app.session_cookie_name,",app.session_cookie_name,)
response.set_cookie(
app.session_cookie_name,
val,
expires=expires,
httponly=httponly,
domain=domain,
path=path,
secure=secure,
samesite=samesite,
)
ナイン、フラッシュ
9.1フラッシュとは何ですか?
-设置:flash('aaa')
-取值:get_flashed_message()
-
-假设在a页面操作出错,跳转到b页面,在b页面显示a页面的错误信息
from flask import Flask,flash,get_flashed_messages
app = Flask(__name__)
#app.session_interface
app.secret_key ="sdasd"
# 什么闪现:就像session一样,也是一个页面设置,另一个页面使用,我不管你在哪个页面调用的
# 只要调用一次,就清空了,
# 闪现的作用,一般用信息处理。假设用户,a页面做操作,产生了信息。我希望在b页面内获取。
# 但是我不知道用户在什么时候,访问b页面,但是只要用户一旦访问页面就把信息显示出来。
# 同一页面,同次请求是可以拿多次的
@app.route("/")
def index():
#产生信息,message设置消息的,category给消息分类,如果不传默认用”message“
flash("你错过了我")
flash(message="你再次错过我",category="渣男")
return "index"
@app.route("/login")
def login():
#(with_categories=True,消息是否要带上分类信息,category_filter=["渣男"]对消息进行过滤,取指定的分类消息
print(get_flashed_messages(with_categories=True,category_filter=["渣男"]))
print(get_flashed_messages())
return "login"
@app.route("/test")
def test():
print(get_flashed_messages())
return "test"
if __name__ == '__main__':
app.run()