Programming

SQLAlchemy 행 항목을 업데이트하는 방법?

procodes 2020. 8. 4. 20:17
반응형

SQLAlchemy 행 항목을 업데이트하는 방법?


가정의 표는 세 개의 열이 있습니다 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변수로 가져올 수 있습니다.

이제 새 객체 변수의 값을 변경하고 의 commit 메소드로 user.no_of_logins += 1변경 사항을 저장할 수 session있습니다.


전보 봇을 작성하고 업데이트 행에 문제가 있습니다. 모델이있는 경우이 예를 사용하십시오.

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 == 6no_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

요점

By referencing the class instead of the instance, you can get SQLAlchemy to be smarter about incrementing, getting it to happen on the database side instead of the Python side. Doing it within the database is better since it's less vulnerable to data corruption (e.g. two clients attempt to increment at the same time with a net result of only one increment instead of two). I assume it's possible to do the incrementing in Python if you set locks or bump up the isolation level, but why bother if you don't have to?

A caveat

If you are going to increment twice via code that produces SQL like SET no_of_logins = no_of_logins + 1, then you will need to commit or at least flush in between increments, or else you will only get one increment in 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

참고URL : https://stackoverflow.com/questions/9667138/how-to-update-sqlalchemy-row-entry

반응형