Я пытаюсь использовать Flask и расширение Flask-Login для реализации аутентификации пользователей в приложении Flask. Цель состоит в том, чтобы вытащить данные учетной записи пользователя из базы данных, а затем войти в систему пользователя, но я застрял; тем не менее, я сузил его до определенной части поведения Flask-Login.
В соответствии с Документация флэшка-входа, мне нужно создать функцию обратного вызова user_loader. Фактическая цель и реализация этой функции заставили меня запутаться в течение нескольких дней:
Вам нужно будет предоставить обратный вызов user_loader. Этот обратный вызов используется для перезагрузки пользовательского объекта из идентификатора пользователя, сохраненного в сеансе. Это должен принимать идентификатор Unicode пользователя и возвращать соответствующий пользовательский объект. Например:
@login_manager.user_loader def load_user(userid): return User.get(userid)
Теперь, скажем, я хочу, чтобы пользователь вводил имя и пароль в форму, проверял базу данных и регистрировал пользователя. Материал базы данных отлично работает и для меня не проблема.
Эта функция обратного вызова хочет передать идентификатор пользователя # и вернуть объект User (содержимое которого я загружаю из базы данных). Но я действительно не понимаю, что он должен проверять/делать, поскольку идентификаторы пользователей все равно вытаскиваются из одного и того же места. Я могу "сортировать" "заставить обратный вызов работать, но он кажется беспорядочным/хакерским, и он попадает в базу данных с каждым единственным ресурсом, который запрашивает браузер. Я действительно не хочу проверять свою базу данных, чтобы загрузить favicon.ico с каждой обновленной страницей, но флажок-логин, похоже, заставляет это.
Если я не проверю базу данных снова, то у меня нет способа вернуть объект 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
"Обратный вызов", который я не совсем понимаю (должен вернуть объект User, который создается после вытаскивания из базы данных):
@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")
Мой код "kinda" работает, я могу войти и выйти, но, как я уже сказал, он должен попасть в базу данных абсолютно для всех, потому что я должен предоставить объект User функции обратного вызова в другом пространстве/области где выполняется остальная часть действия входа. Я почти уверен, что все делаю неправильно, но я не могу понять, как это сделать.
Пример кода, предоставленного флажком-login делает это таким образом, но это работает только потому, что он вытягивает объекты User из глобального жесткого закодированный словарь, а не как в реальном сценарии, например в базе данных, где должна быть проверена БД, и пользовательские объекты, созданные после того, как пользователь вводит свои учетные данные. И я не могу найти какой-либо другой пример кода, который иллюстрирует использование базы данных с флэшем-логином.
Что здесь отсутствует?