Flask-SQLalchemy bir satırın bilgilerini güncelleme


Yanıtlar:


206

Flask-SQLAlchemy belgelerinde gösterilen öğreticiyi kullanarak bir nesneyi alın . Değiştirmek istediğiniz varlığa sahip olduğunuzda, varlığın kendisini değiştirin. Ardından db.session.commit(),.

Örneğin:

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'ye dayalıdır, bu nedenle SQLAlchemy Belgelerine de göz atmayı unutmayın .


2
Teşekkürler Mark. Diğer bir şey. Bunun 'db.add (kullanıcı)' ve ardından 'dv.session.commit ()' gibi yapıldığını gördüm. İkisi de neden çalışıyor? ve fark nedir?
pocorschi

11
Bu, SQLAlchemy'de geçici, ayrılmış ve eklenmiş nesneler arasındaki farklarla ilgilidir (bkz. Sqlalchemy.org/docs/orm/session.html#what-does-the-session-do ). Ayrıca, biraz daha fazla bilgi için posta listesindeki ( groups.google.com/group/sqlalchemy/browse_thread/thread/… ) Michael Bayer'in yorumunu okuyun .
Mark Hildreth

1
Orayı okuduktan sonra hala farklılıklar konusunda kafanız karışıksa, başka bir soru sormayı düşünün.
Mark Hildreth

sütun veri türü json ise aşağıdaki yöntemi kullanın. bashelton.com/2014/03/…
Aram

@MarkHildreth Alana tarih saat değerini güncelleyemedim, ne yapmalıyım? sütun, uesd_at = db.Column(db.DateTime)sadece çalıştırıyorum obj.used_at = datetime.datetime.now() db.session.commit()Ama alana değer ayarlı değil.
Rukeith

96

Bir yöntem yoktur updatetarafından döndürülen SQLAlchemy içinde BaseQuery nesne üzerinde filter_by.

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

Kullanmanın avantajı updateVarlığı değiştirmek yerine güncellenecek çok sayıda nesne olduğunda ortaya çıkar.

add_userTüm e'lere izin vermek istiyorsanız admin,

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

İfade alanların aksine filter_byanahtar kelime argümanları alan (yalnızca birini kullanın =) dikkat edin filter.


1
ilk sorguda, sonuç olarak adlandırılır admin, bu yanıltıcı olabilir çünkü sonuçta güncellenen satır sayısı olacaktır. Değil mi?
Vikas Prasad

ve etkilenen Userkullanıcı sayısı değil de sorgudan etkilenen öğeleri nereden alabileceğim bir yol var mı?
Vikas Prasad

eşleşen
Vikas Prasad

18

Modelin turşu özelliğini değiştirirseniz bu işe yaramaz. Güncellemeleri tetiklemek için turşu özellikleri değiştirilmelidir:

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
Bu tür durumlarda en iyi yaklaşım nedir?
kampta

Kopyalayıp datayeniden atamanız gerekir.
sas

@sas Ne demek istiyorsun?
Mote Zart

Güncelleme mekanizmasını tetiklemek için data özelliğini kopyalamanız ve atamanız gerekir. Aşağıdaki cevaba bir göz atın:user.data = data
sas

9

Sadece değeri atamak ve bunları taahhüt etmek, JSON ve Pickled özellikleri hariç tüm veri türleri için işe yarayacaktır. Yukarıda turşu türü açıklandığı için JSON'ları güncellemenin biraz farklı ama kolay bir yolunu not edeceğim.

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

Modelin yukarıdaki gibi olduğunu varsayalım.

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

Bu, kullanıcıyı {"country": "Sri Lanka"} verileriyle MySQL veritabanına ekler.

Verilerin değiştirilmesi göz ardı edilecektir. Çalışmayan kodum aşağıdaki gibidir.

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'u yeni bir dikteye kopyalamanın (yukarıdaki gibi yeni bir değişkene atamamanın) zahmetli çalışmasından geçmek yerine, işe yaramalıydı, bunu yapmanın basit bir yolunu buldum. JSON'ların değiştirdiği sistemi işaretlemenin bir yolu var.

Çalışma kodu aşağıdadır.

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

Bu harika çalıştı. Bu yöntemle birlikte önerilen başka bir yöntem var var Umarım birine yardım etmişimdir.


2
db.session.merge(user)bu kodu eklemek benim için çalıştı, FYI.
Jeff Bluemel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.