Я пытаюсь использовать Flask и расширение Flask-Loginдля реализации пользователя. аутентификация в приложении Flask. Цель состоит в том, чтобы извлечь информацию об учетной записи пользователя из базы данных, а затем войти в систему пользователя, но я застрял; однако я сузил его до определенной части поведения Flask-Login.
Согласно документации Flask-Login, мне нужно создать функцию обратного вызова user_loader. Фактическая цель и реализация этой функции уже несколько дней смущают меня:
Вам нужно будет обеспечить обратный вызов user_loader. Этот обратный вызов используется для перезагрузки объекта пользователя из идентификатора пользователя, сохраненного в сеансе. Это должен принимать Unicode ID пользователя и возвращать соответствующий пользовательский объект. Например:
@login_manager.user_loader деф load_user (идентификатор пользователя): вернуть пользователя.получить (идентификатор пользователя)
Теперь предположим, что я хочу, чтобы пользователь ввел имя и пароль в форму, сверился с базой данных и зарегистрировался. Материал базы данных работает нормально и не является проблемой для меня.
Эта функция «обратного вызова» хочет получить идентификатор пользователя # и вернуть объект «Пользователь» (содержимое которого я загружаю из базы данных). Но я действительно не понимаю, что он должен проверять/делать, поскольку идентификаторы пользователей все равно берутся из одного и того же места. Я могу «вроде» заставить обратный вызов работать, но он кажется грязным/хакерским, и он попадает в базу данных с каждым ресурсом, который запрашивает браузер. Я действительно не хочу проверять свою базу данных, чтобы загружать favicon.ico при каждом обновлении страницы, но flask-login, похоже, заставляет это делать.
Если я снова не проверю базу данных, у меня не будет возможности вернуть объект пользователя из этой функции. Объект/класс User создается в маршруте flask для входа в систему и, таким образом, выходит за рамки обратного вызова.
Чего я не могу понять, так это того, как передать объект User в эту функцию обратного вызова, не обращаясь каждый раз к базе данных. Или, в противном случае, выяснить, как сделать это более эффективным способом. Должно быть, я упускаю что-то фундаментальное, но я смотрю на это уже несколько дней, бросая на него всевозможные функции и методы, и ничего не получается.
Вот соответствующие фрагменты кода моего теста.Класс User:
class UserClass(UserMixin):
def __init__(self, name, id, active=True):
self.name = name
self.id = id
self.active = active
def is_active(self):
return self.active
Функция, которую я сделал для возврата объекта пользователя в функцию обратного вызова user_loader Flask-Login:
def check_db(userid):
# query database (again), just so we can pass an object to the callback
db_check = users_collection.find_one({ 'userid' : userid })
UserObject = UserClass(db_check['username'], userid, active=True)
if userObject.id == userid:
return UserObject
else:
return None
«Обратный вызов», который я не совсем понимаю (должен возвращать объект пользователя, который создается после извлечение из базы данных):
@login_manager.user_loader
def load_user(id):
return check_db(id)
Маршрут входа в систему:
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST" and "username" in request.form:
username = request.form["username"]
# check MongoDB for the existence of the entered username
db_result = users_collection.find_one({ 'username' : username })
result_id = int(db_result['userid'])
# create User object/instance
User = UserClass(db_result['username'], result_id, active=True)
# if username entered matches database, log user in
if username == db_result['username']:
# log user in,
login_user(User)
return url_for("index"))
else:
flash("Invalid username.")
else:
flash(u"Invalid login.")
return render_template("login.html")
Мой код вроде как работает, я могу войти и выйти, но, как я уже сказал, он должен попадать в базу данных абсолютно для всего, потому что я должен предоставить пользователя объект для функции обратного вызова в другом пространстве имен/области, где происходит остальная часть действия входа. Я почти уверен, что делаю все неправильно, но я не могу понять, как это сделать.
Пример кода, предоставленный flask-login , делает это таким образом, но это работает только потому, что он извлекает объекты User из глобального жестко запрограммированного словаря, а не как в реальном сценарии, таком как база данных, где БД должна быть проверена, а объекты пользователя должны быть созданы после ввода пользователем своих учетных данных для входа. И я не могу найти другого примера кода, иллюстрирующего использование базы данных с flask-login.
Чего здесь не хватает?