Flask-SQLalchemy는 행의 정보를 업데이트합니다.


답변:


205

Flask-SQLAlchemy 설명서에 표시된 자습서를 사용하여 객체를 검색합니다 . 변경하려는 엔티티가 있으면 엔티티 자체를 변경하십시오. 그런 다음 db.session.commit().

예를 들면 :

admin = User.query.filter_by(username='admin').first()
admin.email = 'my_new_email@example.com'
db.session.commit()

user = User.query.get(5)
user.name = 'New Name'
db.session.commit()

Flask-SQLAlchemy는 SQLAlchemy를 기반으로하므로 SQLAlchemy 문서 도 확인하세요 .


2
감사합니다 마크. 한 가지 더. 나는 이것이 'db.add (user)'와 'dv.session.commit ()'과 같이 수행되는 것을 보았습니다. 둘 다 작동하는 이유는 무엇입니까? 그리고 차이점은 무엇입니까?
— pocorschi

11
이는 SQLAlchemy에서 임시, 분리 및 첨부 된 객체 간의 차이점과 관련이 있습니다 ( sqlalchemy.org/docs/orm/session.html#what-does-the-session-do 참조 ). 또한 더 자세한 정보 는 메일 링리스트 ( groups.google.com/group/sqlalchemy/browse_thread/thread/… )에 대한 Michael Bayer의 댓글을 읽어 보세요.
— Mark Hildreth 2011

1
거기를 읽은 후에도 차이점에 대해 혼란 스러우면 다른 질문을 고려하십시오.
— Mark Hildreth 2011

열 데이터 유형이 json이면 아래 방법을 사용하십시오. bashelton.com/2014/03/…
— Aram

@MarkHildreth 필드에 날짜 / 시간 값을 업데이트 할 수 없습니다. 어떻게해야합니까? 열은 uesd_at = db.Column(db.DateTime)방금 실행 obj.used_at = datetime.datetime.now() db.session.commit()했지만 필드에 설정된 값이 아닙니다.
— Rukeith

96

update에서 반환하는 SQLAlchemy의 BaseQuery 개체에 대한 메서드 가 filter_by있습니다.

admin = User.query.filter_by(username='admin').update(dict(email='my_new_email@example.com')))
db.session.commit()

update개체를 변경하는 것보다 사용 하면 업데이트 할 개체가 많을 때 이점이 있습니다.

당신이 부여하려면 add_user모든 권한을 admin의,

rows_changed = User.query.filter_by(role='admin').update(dict(permission='add_user'))
db.session.commit()

공지 filter_by키워드 인수를가 (하나만 사용 =에 반대) filter식을 취한다.


1
첫 번째 쿼리에서 결과 이름은으로 지정 admin됩니다. 결과는 업데이트 된 행 수이므로 오해의 소지가있을 수 있습니다. 그렇지 않나요?
— Vikas Prasad

영향을받는 User사용자 수가 아니라 쿼리를 통해 영향을받는 항목을 가져올 수있는 방법이 있습니까?
— Vikas Prasad

행의 수는 일치
— 카스 프라 사드에게

18

모델의 피클 속성을 수정하면 작동하지 않습니다. 업데이트를 트리거하려면 절인 속성을 교체해야합니다.

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from pprint import pprint

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqllite:////tmp/users.db'
db = SQLAlchemy(app)


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True)
    data = db.Column(db.PickleType())

    def __init__(self, name, data):
        self.name = name
        self.data = data

    def __repr__(self):
        return '<User %r>' % self.username

db.create_all()

# Create a user.
bob = User('Bob', {})
db.session.add(bob)
db.session.commit()

# Retrieve the row by its name.
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {}

# Modifying data is ignored.
bob.data['foo'] = 123
db.session.commit()
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {}

# Replacing data is respected.
bob.data = {'bar': 321}
db.session.commit()
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {'bar': 321}

# Modifying data is ignored.
bob.data['moo'] = 789
db.session.commit()
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {'bar': 321}

1
그러한 경우에 가장 좋은 방법은 무엇입니까?
— kampta

복사 data하고 재 할당해야합니다.
— sas

@sas 무슨 뜻이야?
— Mote Zart

업데이트 메커니즘을 트리거하려면 데이터 속성을 복사하고 할당해야합니다. 아래 답변을보십시오 :user.data = data
— sas

9

값을 할당하고 커밋하면 JSON 및 Pickled 속성을 제외한 모든 데이터 유형에 대해 작동합니다. 피클 유형이 위에서 설명되었으므로 JSON을 업데이트하는 약간 다르지만 쉬운 방법을 기록해 보겠습니다.

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True)
    data = db.Column(db.JSON)

def __init__(self, name, data):
    self.name = name
    self.data = data

모델이 위와 같다고 가정 해 봅시다.

user = User("Jon Dove", {"country":"Sri Lanka"})
db.session.add(user)
db.session.flush()
db.session.commit()

이렇게하면 { "country": "Sri Lanka"} 데이터가있는 MySQL 데이터베이스에 사용자가 추가됩니다.

데이터 수정은 무시됩니다. 작동하지 않은 내 코드는 다음과 같습니다.

user = User.query().filter(User.name=='Jon Dove')
data = user.data
data["province"] = "south"
user.data = data
db.session.merge(user)
db.session.flush()
db.session.commit()

JSON을 새 dict에 복사하는 고통스러운 작업 (위와 같이 새 변수에 할당하지 않음)을 거치는 대신에 간단한 방법을 찾았습니다. JSON이 변경된 시스템에 플래그를 지정하는 방법이 있습니다.

다음은 작업 코드입니다.

from sqlalchemy.orm.attributes import flag_modified
user = User.query().filter(User.name=='Jon Dove')
data = user.data
data["province"] = "south"
user.data = data
flag_modified(user, "data")
db.session.merge(user)
db.session.flush()
db.session.commit()

이것은 매력처럼 작동했습니다. 여기 에이 방법과 함께 제안 된 또 다른 방법이 있습니다 .


2
db.session.merge(user)이 코드를 추가하면 나를 위해 일했습니다.
— Jeff Bluemel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.