2010-11-26 6 views
0

Je me demande mentalement comment faire cela dans Django, en espérant que vous puissiez m'aider.Django: Filtrer des objets avec les résultats d'une autre table?

J'ai une table de galeries que je suis le filtrage par type:

public_galleries = models.Gallery.objects.filter(type = 2).filter(root_gallery__isnull = True) 

mais je veux aussi voir si la galerie n'existe pas dans la table UserGallery pour un utilisateur spécifique. J'ai cette liste de galeries pour l'utilisateur:

user_galleries = models.UserGallery.objects.select_related().filter(clientuser=request.user.id).filter(gallery__root_gallery__isnull = True) 

Note ** Tout a commencé à utiliser Django pour un projet réel, de sorte que toute amélioration ou l'autre de ces déclarations sont également appréciés.

Edition - Les modèles:

class Gallery(models.Model): 
    """Gallery model""" 
    name = models.CharField(u"Gallery name", max_length=120) 
    type = models.IntegerField(default=0, choices=TYPE_CHOICES) 
    root_gallery = models.ForeignKey("self", blank=True, null=True) 
    """ Other Fields""" 

class UserGallery(models.Model): 
    """Model to link Gallery and ClientUser""" 
    gallery = models.ForeignKey(Gallery) 
    clientuser = models.ForeignKey(ClientUser) 
    owner = models.BooleanField(default=False) 
+0

Il est préférable d'inclure les modèles pour toute question Django qui implique de les interroger. –

Répondre

0

Je voudrais remercier Mayuresh, pour son aide

Je ne sais pas pourquoi je suis arrivé cette erreur, mais j'ai trouvé la solution avec ceci:

private_galleries = models.Gallery.objects.filter(type = 1).filter(root_gallery__isnull = True).exclude(id__in = [x.gallery.id for x in user_galleries]) 
5
Gallery.objects.filter(type = 2).filter(root_gallery__isnull = True).exclude(id__in = [x.id for x in request.user.usergallery_set()]) 

devrait le faire.

+0

Ok, donc cela m'a eu la plupart du temps là-bas, je me suis retrouvé avec 'public_galleries = models.Gallery.objects.filter (type = 2) .filter (root_gallery__isnull = Vrai) .exclude (id__in = [x.gallery. id pour x dans user_galleries]) ' –

3

Cette réponse ne fonctionnera pas même pour nombre modérément élevé de user_galleries, puisque vous les chargez tous dans une liste à chaque fois.

Une meilleure méthode consiste à utiliser la méthode extra() de QuerySet, qui vous permet de spécifier des conditions supplémentaires dans SQL pour une clause WHERE.

De la documentation Django:

Vous pouvez définir des clauses explicites SQL WHERE - peut-être effectuer des jointures non explicite - à l'aide d'où. Vous pouvez ajouter manuellement des tables à la clause SQL FROM en utilisant des tables.

Dans votre cas quelque chose comme

private_galleries = Gallery.objects.filter(type=1, root_gallery__isnull=True) \ 
    .extra(where=[''' 
     yourapp_gallery.id NOT IN (SELECT id FROM 
      ...long query used to generate user_galleries... ) 
    ''']) 

fonctionnerait. Malheureusement, cela signifie transcrire la requête qui a produit user_galleries en SQL, vous devez donc décider si le compromis DRY/maintenabilité vaut la peine d'économiser le temps de chargement de cette liste en mémoire à chaque requête. Je soupçonne cela avec n'importe quoi mais un nombre trivial de user_galleries c'est. Notez que where= arg prend une liste de chaînes.

Plus d'infos dans la liste de diffusion here.

Questions connexes