2010-07-20 11 views
2

En résumé, les noms des tables de toutes les requêtes qui se trouvent dans un filtre sont renommés en u0, u1,. .., donc mes clauses supplémentaires where ne sauront pas à quelle table pointer.Je n'aimerais pas avoir à faire toutes les requêtes pour chaque façon que je pourrais sous-sélectionner sur ces données, et ma solution de contournement actuelle est de tourner mon extra d requêtes dans pk values_lists, mais ceux-ci sont vraiment lents et quelque chose d'une abominationdjango's .extra (où = les clauses sont tabassées par un changement de table .filter (foo__in = ... subselects

Voici à quoi tout cela ressemble.Vous pouvez ignorer les détails de ce qui se passe dans les extra de cette méthode de gestionnaire, sauf le premier sql ligne qui pointe vers products_product.id:

def by_status(self, *statii): 
    return self.extra(where=["""products_product.id IN                                     
     (SELECT recent.product_id                                           
      FROM (                                               
      SELECT product_id, MAX(start_date) AS latest                                     
      FROM products_productstatus                                          
      GROUP BY product_id                                            
     ) AS recent                                              
      JOIN products_productstatus AS ps ON ps.product_id = recent.product_id                               
      WHERE ps.start_date = recent.latest                                        
      AND ps.status IN (%s))""" % (', '.join([str(stat) for stat in statii]),)]) 

Ce qui fonctionne à merveille pour toutes les situations impliquant uniquement la table products_product.

Quand je veux que ces produits en tant que sous-sélection, je fais:

Piece.objects.filter(
    product__in=Product.objects.filter(
     pk__in=list(
      Product.objects.by_status(FEATURED).values_list('id', flat=True)))) 

Comment puis-je conserver les capacités générales d'un ensemble de requêtes, mais utilisent encore un supplément where?

+0

Si ce n'était pas évident, je veux voir le "Product.objects.filter (pk__in = list (" partie de cette solution disparaissent – outofculture

+0

Pourriez-vous s'il vous plaît poster le code réel que vous souhaitez utiliser dans votre application et la requête qui serait générée par django (même si c'est avec un mauvais nom de table SQL) Vous pouvez le faire avec 'print Piece.objects.filter (...). query'. Merci! –

+0

Piece.objects.filter (product__in) = Product.objects.by_status (FEATURED)) – outofculture

Répondre

3

Au début, le problème n'est pas totalement clair pour moi. Le deuxième bloc de code de votre question est-il le code que vous voulez exécuter? Si tel est le cas, la requête devrait fonctionner comme prévu, car aucune sous-sélection n'est effectuée.

Je suppose que vous voulez utiliser le deuxième bloc de code sans le list() autour de la sous-sélection pour empêcher une deuxième requête en cours d'exécution. La documentation django fait référence à ce numéro in the documentation about the extra method. Cependant, ce n'est pas très facile de surmonter ce problème. La solution la plus facile mais la plus «hakish» consiste à observer quel alias de table est produit par django pour la table que vous voulez interroger dans la méthode supplémentaire. Vous pouvez compter sur la dénomination persistante de cet alias tant que vous construisez la requête toujours de la même manière (vous ne modifiez pas l'ordre des multiples méthodes extra ou filter qui provoquent une jointure).

Vous pouvez inspecter une requête qui sera exécuter dans le queryset DB en utilisant:

print Model.objects.filter(...).query 

Cela révélera les alias utilisés pour les tables que vous souhaitez interroger.

+0

Droit, je sais que je peux réécrire le supplément où pour utiliser u0, ou parfois u1, en fonction de la situation, mais j'aimerais pouvoir donner à mes gars un modèle/vues un jeu de queues régulier qui fonctionne comme ceux que je leur donne partout ailleurs. – outofculture