Подтвердить что ты не робот

Как обновить запись строки SQLAlchemy?

Предположим, таблица имеет три столбца: username, password и no_of_logins.

Когда пользователь пытается войти, он проверяет запись с запросом вроде

user = User.query.filter_by(username=form.username.data).first()

Если пароль совпадает, он продолжает. То, что я хотел бы сделать, это подсчитать, сколько раз пользователь вошел в систему. Таким образом, всякий раз, когда он успешно входит в систему, я хотел бы увеличить поле no_of_logins и сохранить его обратно в таблицу пользователей. Я не уверен, как запустить запрос на обновление с SqlAlchemy.

4b9b3361

Ответ 1

user.no_of_logins += 1
session.commit()

Ответ 2

Существует несколько способов 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()

Ответ 3

С помощью оператора user=User.query.filter_by(username=form.username.data).first() вы получите указанного пользователя в переменной user.

Теперь вы можете изменить значение новой переменной объекта как user.no_of_logins += 1 и сохранить изменения с помощью метода session commit.

Ответ 4

Я написал бот 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()?

Ответ 5

Примеры для разъяснения важного вопроса в принятых ответах на комментарии

Я не понимал этого, пока сам не поиграл с этим, поэтому я подумал, что будут и другие, которые были бы сбиты с толку. Скажем, вы работаете с пользователем, чей 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