Differenza tra filter e filter_by in SQLAlchemy


304

Qualcuno potrebbe spiegare la differenza tra filtere le filter_byfunzioni in SQLAlchemy? Quale dovrei usare?

Risposte:


393

filter_by è usato per semplici query sui nomi delle colonne usando normali kwarg, come

db.users.filter_by(name='Joe')

Lo stesso può essere realizzato con filter, non usando kwargs, ma usando invece l'operatore di uguaglianza '==', che è stato sovraccaricato sull'oggetto db.users.name:

db.users.filter(db.users.name=='Joe')

Puoi anche scrivere query più potenti utilizzando filter, come espressioni come:

db.users.filter(or_(db.users.name=='Ryan', db.users.country=='England'))


22
Come funziona sotto il cofano? Non db.users.name=='Ryan'valuteresti una volta una costante e da allora in poi non avrebbe più senso? Sembra che uno dovrebbe usare un lambda per farlo funzionare.
Hamish Grubijan,

46
l'operatore di uguaglianza è sovraccarico
Daniel Velkov,

9
type(model.column_name == 'asdf')sqlalchemy.sql.elements.BinaryExpression
Nick T,

11
Fai attenzione quando lo usi .filter. una query come id=12345, query(users).filter(id == id)non filtra users.id. Invece, valuterà id == idcome Truee restituirà tutti gli utenti. Devi usare .filter(users.id == id)(come mostrato sopra). Oggi ho fatto questo errore.
Nico Cernek,

118

In realtà li abbiamo uniti insieme in origine, ovvero esisteva un metodo simile a "filtro" che accettava *argse **kwargs, in cui si potevano passare espressioni SQL o argomenti di parole chiave (o entrambi). In realtà lo trovo molto più conveniente, ma le persone ne sono sempre state confuse, dal momento che di solito continuano a superare la differenza tra column == expressione keyword = expression. Quindi li abbiamo divisi.


30
Penso che il tuo punto su column == expressionvs. keyword = expressionsia il punto chiave da fare sulla differenza tra filtere filter_by. Grazie!
Hollister,

2
Sono nuovo di sqlalchemy, quindi mi scusi se questa è una domanda stupida, ma filter_by () non sembra consentire nemmeno le condizioni molto semplici come "prezzo> = 100". Quindi, perché avere la funzione filter_by () comunque, se puoi usarla solo per la condizione più semplice come "prezzo = 100"?
PawelRoman,

18
perché piace alla gente
zzzeek,

3
C'è qualche differenza di prestazioni tra loro? Stavo pensando che filter_bypotrebbe essere un po 'più veloce di filter.
Devi

6
Il punto di utilizzo filter_byè di poter scrivere solo il nome del campo, per quella classe, senza fare domande - mentre flterrichiede l'oggetto colonna reale - che di solito richiederà uno per digitare (e leggere) almeno un nome di classe ridondante. Quindi, se si vuole filtrare per uguaglianza, è piuttosto conveniente.
jsbueno,

36

filter_byusa argomenti di parole chiave, mentre filterconsente argomenti di filtro pythonic comefilter(User.name=="john")


34

È uno zucchero sintattico per una scrittura più veloce delle query. La sua implementazione in pseudocodice:

def filter_by(self, **kwargs):
    return self.filter(sql.and_(**kwargs))

Per AND puoi semplicemente scrivere:

session.query(db.users).filter_by(name='Joe', surname='Dodson')

btw

session.query(db.users).filter(or_(db.users.name=='Ryan', db.users.country=='England'))

può essere scritto come

session.query(db.users).filter((db.users.name=='Ryan') | (db.users.country=='England'))

Inoltre puoi ottenere l'oggetto direttamente tramite PK tramite il getmetodo:

Users.query.get(123)
# And even by a composite PK
Users.query.get(123, 321)

Quando si utilizza getcase è importante che l'oggetto possa essere restituito senza la richiesta del database da identity mapcui può essere usato come cache (associato alla transazione)


Questi esempi di codice sono fuorvianti: le classi e le istanze della tabella di base dichiarative non hanno né filtri né metodi di query; usano la sessione.
tartarughe sono carine il

Mi riproduco users.filterdalla risposta precedente. E potrebbe essere colpa mia :) l' queryattributo è query_property ed è abbastanza uno zucchero standard al giorno d'oggi
enomad
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.