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.