2015-10-04 17 views
10

Ho un'applicazione Flask che usa Flask-SQLAlchemy per connettersi a un database MySQL.Flask-SQLAlchemy controlla se esiste una riga nella tabella

Vorrei poter controllare se una riga è presente in una tabella. Come potrei modificare una query in questo modo per controllare la riga esiste:

db.session.query(User).filter_by(name='John Smith') 

ho trovato una soluzione sulla this question che usa SQLAlchemy ma non sembra adattarsi con il modo in cui Flask-SQLAlchemy funziona:

from sqlalchemy.sql import exists  
print session.query(exists().where(User.email == '...')).scalar() 

Grazie.

+0

In che modo la prima query * non * verificare che esiste la fila? –

+0

Vorrei che la query restituisse 'True' o' False' se la riga esiste. –

+0

Cosa c'è che non va nel secondo metodo? Funziona bene in Flask-SQLAlchemy, l'ho appena provato. – davidism

risposta

16

Poiché si desidera solo vedere se l'utente esiste, non si desidera interrogare l'intero oggetto. Basta interrogare l'id, esiste se il ritorno scalare non è None.

exists = db.session.query(User.id).filter_by(name='davidism').scalar() is not None 

La seconda query hai mostrato anche funziona bene, Flask-SQLAlchemy non fa nulla per prevenire qualsiasi tipo di query che SQLAlchemy può fare.

exists = db.session.query(db.exists().where(User.name == 'davidism')).scalar() 
8

Avvolgere una query .exists() in un altro session.query() con un scalar() chiamata al termine.

exists = db.session.query(
    db.session.query(User).filter_by(name='John Smith').exists() 
).scalar() 
+0

Dovresti davvero interrogare 'User.id', altrimenti stai facendo in modo che SQLAlchemy generi una query molto più ampia del necessario. Questo è anche lo stesso del mio secondo esempio, usando semplicemente 'query.exists' invece di' db.exists', che sono essenzialmente la stessa cosa. – davidism

+0

@davidism SQLAlchemy lo traduce in 'SELECT EXISTS (SELECT 1 FROM user WHERE user.name =?)'. Questa è una query leggermente più lunga di "SELECT user.id FROM user WHERE user.name =?", Ma riflette in modo più accurato la domanda effettiva che viene posta. Allo stesso modo, sul lato Python, il codice sembra molto simile a quello di recuperare un utente, il che rende la query facile da ricordare e capire. – lyschoening

+0

Esistono due query diverse? Interessante, dovrò controllare, non ho fatto una tal domanda in un istante. – davidism

0

Perdonate il dirottamento, ma ... con le istruzioni riportate qui ho fatto la seguente WTForm validatore per verificare l'unicità del campo

class Unique(object): 
    def __init__(self, column, session, message="Already exists."): 
     self.column = column 
     self.session = session 
     self.message = message 

    def __call__(self, form, field): 
     if field.data == field.object_data: 
      return # Field value equals to existing value. That's ok. 
     model = self.column.class_ 
     query = model.query.filter(self.column == field.data).exists() 
     if self.session.query(query).scalar(): 
      raise ValidationError(self.message) 

che sarebbe stato usato come questo

class Register(Form): 
    email = EmailField('Email', [Unique(User.email, db.session)]) 

Tuttavia, mi piacerebbe avere l'API che non ha bisogno della sessione db come secondo param

class Register(Form): 
    email = EmailField('Email', [Unique(User.email)]) 

C'è un modo per ottenere la sessione db dal modello? Senza sessione sembra impossibile evitare di caricare l'intero oggetto per verificarne l'esistenza.

-2

che ci sia un errore di battitura nella risposta di davidism, questo funziona per me:

exists = db.session.query(**User**).filter_by(name='davidism').scalar() is not None 
+0

Non è un refuso, sto specificatamente interrogando l'id perché il recupero dell'intero oggetto è eccessivo per il controllo dell'esistenza. – davidism

Problemi correlati