Ответ 1
user.no_of_logins += 1
session.commit()
Предположим, таблица имеет три столбца: username
, password
и no_of_logins
.
Когда пользователь пытается войти, он проверяет запись с запросом вроде
user = User.query.filter_by(username=form.username.data).first()
Если пароль совпадает, он продолжает. То, что я хотел бы сделать, это подсчитать, сколько раз пользователь вошел в систему. Таким образом, всякий раз, когда он успешно входит в систему, я хотел бы увеличить поле no_of_logins
и сохранить его обратно в таблицу пользователей. Я не уверен, как запустить запрос на обновление с SqlAlchemy.
user.no_of_logins += 1
session.commit()
Существует несколько способов UPDATE
с помощью sqlalchemy
1) user.no_of_logins += 1
session.commit()
2) session.query().\
filter(User.username == form.username.data).\
update({"no_of_logins": (User.no_of_logins +1)})
session.commit()
3) conn = engine.connect()
stmt = User.update().\
values(no_of_logins=(User.no_of_logins + 1)).\
where(User.username == form.username.data)
conn.execute(stmt)
4) setattr(user, 'no_of_logins', user.no_of_logins+1)
session.commit()
С помощью оператора user=User.query.filter_by(username=form.username.data).first()
вы получите указанного пользователя в переменной user
.
Теперь вы можете изменить значение новой переменной объекта как user.no_of_logins += 1
и сохранить изменения с помощью метода session
commit.
Я написал бот Telegram, и у меня возникли проблемы с обновлением строк. Используйте этот пример, если у вас есть Модель
def update_state(chat_id, state):
try:
value = Users.query.filter(Users.chat_id == str(chat_id)).first()
value.state = str(state)
db.session.flush()
db.session.commit()
#db.session.close()
except:
print('Error in def update_state')
Зачем использовать db.session.flush()
? Вот почему >>> SQLAlchemy: В чем разница между flush() и commit()?
Я не понимал этого, пока сам не поиграл с этим, поэтому я подумал, что будут и другие, которые были бы сбиты с толку. Скажем, вы работаете с пользователем, чей id == 6
и чей no_of_logins == 30
при запуске.
# 1 (bad)
user.no_of_logins += 1
# result: UPDATE user SET no_of_logins = 31 WHERE user.id = 6
# 2 (bad)
user.no_of_logins = user.no_of_logins + 1
# result: UPDATE user SET no_of_logins = 31 WHERE user.id = 6
# 3 (bad)
setattr(user, 'no_of_logins', user.no_of_logins + 1)
# result: UPDATE user SET no_of_logins = 31 WHERE user.id = 6
# 4 (ok)
user.no_of_logins = User.no_of_logins + 1
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6
# 5 (ok)
setattr(user, 'no_of_logins', User.no_of_logins + 1)
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6
Ссылаясь на класс вместо экземпляра, вы можете заставить SQLAlchemy быть более умным в отношении приращения, чтобы это происходило на стороне базы данных, а не на стороне Python. Делать это в базе данных лучше, поскольку она менее уязвима к повреждению данных (например, два клиента пытаются одновременно увеличиваться с чистым результатом только одного приращения вместо двух). Я предполагаю, что можно делать инкремент в Python, если вы устанавливаете блокировки или повышаете уровень изоляции, но зачем беспокоиться, если вам это не нужно?
Если вы собираетесь увеличивать дважды с помощью кода, который генерирует SQL, например, SET no_of_logins = no_of_logins + 1
, то вам нужно будет зафиксировать или хотя бы сбрасывать между приращениями, иначе вы получите всего один прирост:
# 6 (bad)
user.no_of_logins = User.no_of_logins + 1
user.no_of_logins = User.no_of_logins + 1
session.commit()
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6
# 7 (ok)
user.no_of_logins = User.no_of_logins + 1
session.flush()
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6
user.no_of_logins = User.no_of_logins + 1
session.commit()
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6