2010-02-07 29 views
69

Ho un modello:filtro Django ManyToMany()

class Zone(models.Model): 
    name = models.CharField(max_length=128) 
    users = models.ManyToManyField(User, related_name='zones', null=True, blank=True) 

e ho bisogno di contruct un filtro lungo le linee di:

u = User.objects.filter(...zones contains a particular zone...) 

deve essere un filtro su Utente e ha essere un parametro di filtro singolo. La ragione di questo è che sto costruendo un URL querystring per filtrare l'elenco degli utenti amministratore: http://myserver/admin/auth/user/?zones=3

Sembra che dovrebbe essere semplice ma il mio cervello non sta collaborando!

+7

non sono sicuro se ho te in questo - non è 'User.objects.filter (zones__id = )' o 'User.objects.filter (zones__in = ) 'buono per questo? –

+0

Va bene :) BTW 'User.objects.filter (zones__in = )' dovrebbe probabilmente essere 'User.objects.filter (zones__id__in = )' –

+10

Volevo solo far notare a chiunque usi Google questo, che funziona solo se related_name è impostato. zone_set non funzionerebbe, per esempio. Ho sprecato una buona mezz'ora su questo :-) –

risposta

77

Proprio ripensando a quello che ha detto Tomasz.

Esistono molti esempi di filtri di stile FOO__in=... nei test many-to-many e many-to-one. Ecco la sintassi per il vostro problema specifico:

users_in_1zone = User.objects.filter(zones__id=<id1>) 
# same thing but using in 
users_in_1zone = User.objects.filter(zones__in=[<id1>]) 

# filtering on a few zones, by id 
users_in_zones = User.objects.filter(zones__in=[<id1>, <id2>, <id3>]) 
# and by zone object (object gets converted to pk under the covers) 
users_in_zones = User.objects.filter(zones__in=[zone1, zone2, zone3]) 

La sintassi doppia sottolineatura (__) è utilizzato in tutto il posto quando si lavora con querysets.

+0

il link del documento è ora rotto, ma grazie istruttivo! – maxm

+0

Grazie a @maxm. Aggiornato con un collegamento più aggiornato ad alcuni esempi. – istruble

+0

il link è rotto – maazza

10

Si noti che se l'utente può trovarsi in più zone utilizzate nella query, è probabile che si desideri aggiungere .distinct(). In caso contrario, si ottiene uno degli utenti più volte:

users_in_zones = User.objects.filter(zones__in=[zone1, zone2, zone3]).distinct() 
Problemi correlati