Flask-SQLalchemy aggiorna le informazioni di una riga


Risposte:


206

Recupera un oggetto utilizzando il tutorial mostrato nella documentazione di Flask-SQLAlchemy . Una volta che hai l'entità che vuoi cambiare, cambia l'entità stessa. Poi, db.session.commit().

Per esempio:

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 è basato su SQLAlchemy, quindi assicurati di controllare anche i documenti di SQLAlchemy .


2
Grazie Marco. Un'altra cosa. L'ho visto fare in questo modo 'db.add (user)' quindi 'dv.session.commit ()'. Perché funzionano entrambi? e qual è la differenza?
pocorschi

11
Ciò ha a che fare con le differenze tra oggetti temporanei, scollegati e associati in SQLAlchemy (vedere sqlalchemy.org/docs/orm/session.html#what-does-the-session-do ). Inoltre, leggi il commento di Michael Bayer sulla mailing list ( groups.google.com/group/sqlalchemy/browse_thread/thread/… ) per ulteriori informazioni.
Mark Hildreth

1
Se sei ancora confuso sulle differenze dopo aver letto tutto, considera di fare un'altra domanda.
Mark Hildreth

se il tipo di dati della colonna è json, utilizzare il metodo seguente. bashelton.com/2014/03/…
Aram

@ MarkHildreth Non sono riuscito ad aggiornare un valore datetime nel campo, cosa devo fare? la colonna è uesd_at = db.Column(db.DateTime)Ho appena eseguito obj.used_at = datetime.datetime.now() db.session.commit()ma non il valore impostato sul campo.
Rukeith

96

Esiste un metodo updatesull'oggetto BaseQuery in SQLAlchemy, che viene restituito da filter_by.

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

Il vantaggio di utilizzare updaterispetto alla modifica dell'entità si ha quando ci sono molti oggetti da aggiornare.

Se vuoi dare il add_userpermesso a tutti admini,

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

Si noti che filter_byaccetta argomenti di parole chiave (usane solo uno =) al contrario di filterquali accetta un'espressione.


1
nella prima query, il risultato è denominato come admin, il che potrebbe essere fuorviante poiché il risultato sarà il numero di righe aggiornate. Non è vero?
Vikas Prasad

e c'è un modo in cui posso ottenere gli Userelementi interessati dalla query, non il numero di utenti interessati?
Vikas Prasad

numero di file abbinate
Vikas Prasad

18

Questo non funziona se si modifica un attributo decapato del modello. Gli attributi in salamoia devono essere sostituiti per attivare gli aggiornamenti:

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
Qual è l'approccio migliore in questi casi?
kampta

Dovresti copiarlo datae riassegnarlo.
sas

@sas Cosa intendi?
Mote Zart

Dovrai copiare e assegnare alla proprietà data per attivare il meccanismo di aggiornamento. Dai un'occhiata alla risposta qui sotto:user.data = data
sas

9

La semplice assegnazione del valore e il loro commit funzioneranno per tutti i tipi di dati tranne gli attributi JSON e Pickled. Poiché il tipo in salamoia è spiegato sopra, annoterò un modo leggermente diverso ma semplice per aggiornare i 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

Diciamo che il modello è come sopra.

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

Questo aggiungerà l'utente al database MySQL con i dati {"country": "Sri Lanka"}

La modifica dei dati verrà ignorata. Il mio codice che non ha funzionato è il seguente.

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

Invece di passare attraverso il doloroso lavoro di copiare il JSON in un nuovo dict (non assegnarlo a una nuova variabile come sopra), che avrebbe dovuto funzionare, ho trovato un modo semplice per farlo. C'è un modo per contrassegnare il sistema che i JSON sono cambiati.

Di seguito è riportato il codice di lavoro.

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

Questo ha funzionato come un fascino. C'è un altro metodo proposto insieme a questo metodo qui Spero di aver aiutato qualcuno.


2
db.session.merge(user)l'aggiunta di questo codice ha funzionato per me, FYI.
Jeff Bluemel
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.