2012-04-16 12 views
6

ho i seguenti modelli:Escludere intera QuerySet dai risultati

class LibraryEntry(models.Model): 
    player = models.ForeignKey(Player) 
    player_lib_song_id = models.IntegerField() 
    title = models.CharField(max_length=200) 
    artist = models.CharField(max_length=200) 
    album = models.CharField(max_length=200) 
    track = models.IntegerField() 
    genre = models.CharField(max_length=50) 
    duration = models.IntegerField() 
    is_deleted = models.BooleanField(default=False) 

    class Meta: 
    unique_together = ("player", "player_lib_song_id") 

    def __unicode__(self): 
    return "Library Entry " + str(self.player_lib_song_id) + ": " + self.title 

class BannedSong(models.Model): 
    lib_entry = models.ForeignKey(LibraryEntry) 

    def __unicode__(self): 
    return "Banned Library Entry " + str(self.lib_entry.title) 

Mi piacerebbe fare una query come questa:

banned_songs = BannedSong.objects.filter(lib_entry__player=activePlayer) 
available_songs = LibraryEntry.objects.filter(player=activePlayer).exclude(banned_songs) 

In pratica se una canzone è vietato, voglio escludere dal mio set di canzoni disponibili. C'è un modo per farlo in Django?

+0

si fa a non fare 'is_banned' un campo booleano del modello LibraryEntry? – jimw

+0

Sì, ma pochissime canzoni saranno effettivamente bannate rispetto al numero che non lo sono. Ho pensato di aggiungere un campo booleano che per la maggior parte sarà solo un valore è una cattiva forma. –

+1

Non lo direi, ma suppongo sia una questione di gusti. – jimw

risposta

11
banned_song_ids = (BannedSong.objects.filter(lib_entry__player=activePlayer) 
              .values_list('lib_entry', flat=True)) 

available_songs = (LibraryEntry.objects.filter(player=activePlayer) 
              .exclude('id__in' = banned_song_ids)) 

L'alternativa è:

available_songs = (LibraryEntry.objects.filter(player=activePlayer) 
              .filter(bannedsong__isnull = True)) 
+0

Ho provato prima questo in realtà e non funziona. Django confronta il campo ID di ogni set. Voglio che confronti il ​​campo id del set LibraryEntry con il campo lib_id del set banned_songs. Non confrontare ID id. –

+0

@KurtisNusbaum L'ho scritto prima di rendermi conto che 'banned_songs' era un queryset di un modello diverso, piuttosto che dello stesso modello. L'ho aggiornato per usare un 'values_list'. – agf

+0

Fantastico. Questo dovrebbe funzionare abbastanza bene in realtà. Anche se ho paura di alcuni problemi di prestazioni nel caso in cui banned_songs sia grande. Ma come ho detto, non prevedo che sia grande. Se faccio un OneToOneField invece di una chiave esterna, questo cambia le cose? –

Problemi correlati