декоратор для изменения функции просмотра logi c, если пользователь анонимный - PullRequest
0 голосов
/ 30 апреля 2020

В настоящее время у меня есть представление, которое возвращает разные ответы в зависимости от того, является ли пользователь анонимным или нет, я использую:

@app.route("/anonymous")
def anonymous_page():
    if current_user.is_anonymous:
        return render_template("anonymous_page.html")
    return render_template("user_page.html")

Я хочу создать декоратор, назовем его @show_only_to_anonymous , которая может быть использована в обычной функции представления с одним оператором return, который будет делать что-то вроде этого:

@app.route("/anonymous")
@show_only_to_anonymous
# if the user is anonymous, return the decorated function's view,
# elif the user is NOT anonymous, return "user_page.html"
def anonymous_page():
        return render_template("anonymous_page.html")

Я знаю, что есть login_required декоратор, я пошел посмотреть на исходный код здесь , и он использует LocalProxy для current_user под колпаком, попытался повторить это и потерпел неудачу,

Я думаю, что мое понимание структуры flask отсутствует как Я новичок в этом, у кого-нибудь есть идея?

edit: мне удалось заставить ее работать, посмотрев на исходный код flask -login, файл: flask_login/utils.py, я использовал те же самые функции flask и werkzeug.local и другие объекты и создали новый файл в моем проекте, который я назвал custom_decorators.py и импортировал как модуль в мой файл routes.py, это содержимое custom_decorators.py:

from functools import wraps
from werkzeug.local import LocalProxy
from flask import _request_ctx_stack, has_request_context, current_app

current_user = LocalProxy(lambda: _get_user())

def _get_user():
    if has_request_context() and not hasattr(_request_ctx_stack.top, 'user'):
        current_app.login_manager._load_user()

    return getattr(_request_ctx_stack.top, 'user', None)

def show_only_to_anonymous(func):
    @wraps(func)
    def decorated_view(*args, **kwargs):
        if not current_user.is_anonymous:
            return current_app.view_functions['show_to_known_users'](*args, **kwargs)
        return func(*args, **kwargs)
    return decorated_view

сейчас в моем routes.py Я могу сделать это:

# this page can only be seen by anonymous users
@app.route("/anonymous")
@show_only_to_anonymous
def anonymous_page():
    return render_template("anonymous_page.html")

# this will be called if a logged in user goes to mywebsite.com/anonymous:
@app.route("/show_to_known_users")
def show_to_known_users():
    return redirect(url_for("user_page.html", code=301))

th решение выглядит немного «хакерским», есть ли лучший способ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...