2011-07-14 8 views

Odpowiedz

109

pobrać obiekt za pomocą tutorial shown in the Flask-SQLAlchemy documentation. Kiedy już masz byt, który chcesz zmienić, zmień sam obiekt. Następnie db.session.commit().

Na przykład:

admin = User.query.filter_by(username='admin').first() 
admin.email = '[email protected]' 
db.session.commit() 

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

skrzynkowego SQLAlchemy jest oparta na SQLAlchemy, więc pamiętaj o: sprawdzeniu SQLAlchemy Docs również.

+1

Dzięki Mark. Jeszcze jedna rzecz. Widziałem, jak to robiono "db.add (użytkownik)", a następnie "dv.session.commit()". Dlaczego oba działają?i jaka jest różnica? – pocorschi

+8

Ma to związek z różnicami między obiektami przejściowymi, odłączonymi i dołączonymi w SQLAlchemy (zobacz http://www.sqlalchemy.org/docs/orm/session.html#what-does-the-session-do). Przeczytaj także komentarz Michaela Bayera na liście mailingowej (http://groups.google.com/group/sqlalchemy/browse_thread/thread/e38e2aba57aeed92?pli=1), aby uzyskać więcej informacji. –

+1

Jeśli nadal jesteś zdezorientowany różnicami po przeczytaniu tam, rozważ zadawanie innego pytania. –

50

Istnieje metoda update dla obiektu BaseQuery w SQLAlchemy, która jest zwracana przez filter_by.

admin = User.query.filter_by(username='admin').update(dict(email='[email protected]'))) 
db.session.commit() 

Zaletą korzystania update nad zmianą podmiotu przychodzi, gdy istnieje wiele obiektów mają być aktualizowane.

Jeśli chcesz dać add_user pozwolenie na wszystkich admin s

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

Uwaga, filter_by bierze argumenty słów kluczowych (tylko jeden = używania), w przeciwieństwie do filter który trwa wyrażenia.

13

To nie działa, jeśli modyfikuje się piklowany atrybut modelu. Marynowane atrybuty powinny zostać zastąpione w celu uruchomienia aktualizacji:

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

Jakie jest najlepsze podejście w takich przypadkach? – kampta

+0

Musisz skopiować "dane" i ponownie przypisać. – sas

3

Wystarczy przypisywania wartości i zobowiązując je będzie działać dla wszystkich typów danych, ale JSON i marynowane atrybutów. Ponieważ wytłuszczony typ jest wyjaśniony powyżej, zapiszę nieco inny, ale łatwy sposób na aktualizację JSON-ów.

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 

Załóżmy, że model wygląda jak wyżej.

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

Będzie dodać użytkownika do bazy danych MySQL z danymi { "kraju": "Sri Lanka"}

Modyfikowanie dane zostaną zignorowane. Mój kod, który nie działał, jest następujący.

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() 

Zamiast przeżywa bolesne pracy kopiowania JSON do nowego dict (nie przypisaniem go do nowej zmiennej, jak wyżej), które powinny pracował znalazłem prosty sposób aby to zrobić. Istnieje sposób oznaczenia systemu, który zmienił system JSON.

Poniżej znajduje się działający kod.

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() 

To działało jak czar. Jest jeszcze jedna metoda zaproponowana wraz z tą metodą. here Mam nadzieję, że pomogłem komuś.