Catalog
If one day the business requirements of the company need to add functions to all view functions, it can be realized through decorators, but there are too many view functions, is there a better way?
Before request and after request are very simple. The functions in the implementation are the same as those of the middleware process request and process response in Django
1. Premise, disadvantages of decorator
Now we have a Flask program, which has three routing and view functions, as follows:
from flask import Flask app = Flask(__name__) # type:Flask @app.route("/login") def login(): return "Login" @app.route("/index") def index(): return "Index" @app.route("/home") def home(): return "Login" app.run("0.0.0.0", 5000)
from flask import Flask app = Flask(__name__) # type:Flask @app.route("/login") def login(): return "Login" @app.route("/index") def index(): return "Index" @app.route("/home") def home(): return "Login" app.run("0.0.0.0", 5000)
If you log in, you can visit the index and home pages. If you don't log in, you can jump to login
How to solve this problem? Session pair. Use all functions except Login function of session to check whether session is logged in
It's too much trouble. Now we only have three functions. If there are hundreds of functions, how can they be integrated
Decorator, yes, decorator is a good solution, but ah, I still have thousands of functions. It's still troublesome for me to add @ decorator to every function definition
2. Before & after request
2.1 before Ou request analysis:
from flask import Flask, render_template app = Flask(__name__) @app.route("/home") def home(): return "Hello" @app.before_request def be1(): print("be1") return "Error" # return None @app.before_request def be2(): print("be2") return None @app.after_request def af1(res): print("af1") return res @app.after_request def af2(res): print("af2") return res if __name__ == '__main__': app.run()
Error message:
#In Django, if the request directly fails to meet the conditions to return when it reaches request 1, that is, return HttpResponse("Md1 interrupt"), the program will send the request directly to middleware 1 to return, and then return to the requester in turn, and no longer execute the view function #In Flask, if the request directly fails to meet the conditions when it reaches request 1, it will return to the requester in turn in the last @ app.after \ Return to the page interrupted by Md2, and print in the background as follows: be1 af2 af1
2.2 after request analysis:
@If the app.after'request reports an error, the results will be returned in turn
from flask import Flask, render_template app = Flask(__name__) @app.route("/home") def home(): return "Hello" @app.before_request def be1(): print("be1") # return "there is an error." return None @app.before_request def be2(): print("be2") return None @app.after_request def af1(res): print("af1") return res @app.after_request def af2(res): print("af2") # return res return "Error" if __name__ == '__main__': app.run()
Error message:
# Return result be1 be2 af2 af1
3. Before you request application
@App.before-u request is executed before the request enters the view function
@App.before'u request is also a decorator. All functions decorated by it will be executed before the request enters the view function
request.path is to read the current url address. If it is / login, it is allowed to directly pass return None, which can be understood as pass
Verify whether there is user in the session. If not, it indicates that there is no login. Therefore, the merciless redirect("/login") will jump to the login page
There is another @app.before_first_request to be mentioned, which is very similar to or similar to @app.before_request, but it will only be executed once.
from flask import Flask from flask import request from flask import redirect from flask import session app = Flask(__name__) # type:Flask app.secret_key = "DragonFire" @app.before_request def is_login(): #White list if request.path == "/login": return None #Verify session if not session.get("user"): return redirect("/login") return None @app.route("/login") def login(): return "Login" @app.route("/index") def index(): return "Index" @app.route("/home") def home(): return "Login" app.run("0.0.0.0", 5000)
4. Before you request application
@App.after'request is executed before the response is returned to the client, and after the view function is ended
@App.after'request must return the parameter environ of the previous layer, otherwise an error will be reported
@app.after_request def foot_log(environ): if request.path != "/login": print("There's a visitor",request.path) return environ
5. Implement a simple page login with flash
Authentication login based on before request and after request
from flask import Flask,render_template,request,redirect,session app = Flask(__name__,template_folder='templates') app.secret_key = "sdsfdsgdfgdfgfh" @app.before_request def process_request(): if request.path=="/login": return None if not session.get("user_info"): return redirect("/login") return None @app.after_request def process_response(response): print(2222) return response @app.route("/login",methods=["GET","POST"]) def login(): if request.method=="GET": return render_template("login.html") else: # print(request.values) #There's everything in this. It's like a body username = request.form.get("username") password = request.form.get("password") if username=="annie" and password=="123": session["user_info"] = username # session.pop("user_info") #Delete session return redirect("/index") else: # return render_template("login.html",**{"msg": "wrong user name or password"}) return render_template("login.html",msg="Wrong user name or password") @app.route("/index",methods=["GET","POST"]) def index(): # if not session.get("user_info"): # return redirect("/login") return render_template("index.html") if __name__ == '__main__': app.run(debug=True)