Como atualizar a entrada de linha SQLAlchemy?
-
12-12-2019 - |
Pergunta
Suponha que a tabela tenha três colunas: username
, password
e no_of_logins
.
Quando o usuário tenta fazer login, é verificada uma entrada com uma consulta como
user = User.query.filter_by(username=form.username.data).first()
Se a senha corresponder, ele prossegue.O que eu gostaria de fazer é contar quantas vezes o usuário efetuou login.Assim, sempre que ele fizer login com sucesso, gostaria de incrementar o no_of_logins
campo e armazene-o de volta na tabela do usuário.Não sei como executar a consulta de atualização com o SqlAlchemy.
Solução
user.no_of_logins += 1
session.commit()
Outras dicas
Existem várias maneiras de UPDATE
usando 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()
Exemplos para esclarecer a questão importante nos comentários das respostas aceitas
Eu não entendi até que brinquei sozinho, então imaginei que haveria outras pessoas que também ficariam confusas.Digamos que você esteja trabalhando no usuário cujo id == 6
e cujo no_of_logins == 30
quando você começar.
# 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
O ponto
Ao referenciar a classe em vez da instância, você pode fazer com que o SQLAlchemy seja mais inteligente no incremento, fazendo com que isso aconteça no lado do banco de dados em vez do lado do Python.Fazer isso dentro do banco de dados é melhor, pois é menos vulnerável à corrupção de dados (por exemplo,dois clientes tentam incrementar ao mesmo tempo com um resultado líquido de apenas um incremento em vez de dois).Presumo que seja possível fazer o incremento em Python se você definir bloqueios ou aumentar o nível de isolamento, mas por que se preocupar se não é necessário?
Uma advertência
Se você for incrementar duas vezes por meio de código que produz SQL como SET no_of_logins = no_of_logins + 1
, então você precisará confirmar ou pelo menos liberar entre os incrementos, ou então obterá apenas um incremento no total:
# 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
Com a ajuda de user=User.query.filter_by(username=form.username.data).first()
declaração você obterá o usuário especificado em user
variável.
Agora você pode alterar o valor da nova variável de objeto como user.no_of_logins += 1
e salve as alterações com o session
método de confirmação.
Escrevi um bot de telegrama e tenho alguns problemas com as linhas de atualização.Use este exemplo, se você tiver Model
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')
Por que usar db.session.flush()
?É por isso >>> SQLAlquimia:Qual é a diferença entre flush() e commit()?