# Making a 'login required' decorator
List of all code changes made in this lecture: https://diff-store.com/diff/section13__05_login_required_decorator (opens new window)
Earlier this section we wrote a simple check in our
/protected endpoint which acted as a gate for logged-out users.
If the user is not logged in, they are redirected to the login page. Otherwise, the rest of the route runs as normal.
This is such a common thing to do, that it's likely almost all your endpoints will have a check like that one:
@app.get("/protected") def protected(): if not session.get("email"): abort(401) return render_template("protected.html")
# Writing the decorator
A decorator in Python is a function that acts on another function, extending it by running some code either before or after it.
I'd recommend learning about decorators in depth before continuing!
Here's what our decorator looks like:
def login_required(route): @functools.wraps(route) def route_wrapper(*args, **kwargs): if session.get("email") is None: return redirect(url_for("login")) return route(*args, **kwargs) return route_wrapper
And this is how we use it:
@app.get("/protected") +@login_required def protected(): return render_template("protected.html")
With that, the
protected function is replaced by the
route_wrapper function (although it keeps its name and docstring, if any):
def route_wrapper(*args, **kwargs): if session.get("email") is None: return redirect(url_for("login")) return route(*args, **kwargs)
route(*args, **kwargs) is calling what was previously the
protected function. What we've done is extracted the log in check so that any of our endpoints can be decorated with
@login_required so the check runs before anything else does in the endpoint.