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.