2012-07-06 1 views
2

Je ces modèles:Django ManyToManyField filtre avec des paramètres?

class Category(Model): 
    ... 
    type = models.CharField(max_length=255, choices=settings.CATEGORIES) 

class Product(models.Model): 
    ... 
    categories = models.ManyToManyField(Category) 

J'ai la liste des catégories, entrées par l'utilisateur (format est arbitraire):

c = [<Category: G, type: producer>, <Category: L, type: producer>, <Category: Teen, type: age>, <Category: Man, type: sex>] 

Maintenant, je veux avoir tous les produits dans les catégories ont G 'ou' L 'avec le type' producteur ',' Teen 'avec le type' age 'et' Man 'avec le type' sexe '. Je fais par exemple suivant queryset:

Product.objects.filter(Q(categories=c[0])|Q(categories=c[1]), Q(categories=c[2]), Q(categories=c[3]) 

qui ont une telle requête:

SELECT "shop_product"."id", "shop_product"."title", "shop_product"."description", 
"shop_product"."price", "shop_product"."code", "shop_product"."stored_count", 
"shop_product"."sold_count", "shop_product"."added_date" FROM "shop_product" 
INNER JOIN  "shop_product_categories" ON ("shop_product"."id" = 
"shop_product_categories"."product_id") WHERE 
(("shop_product_categories"."category_id" = 1 OR 
"shop_product_categories"."category_id" = 2) AND  
"shop_product_categories"."category_id" = 4 AND 
"shop_product_categories"."category_id" = 6) 

J'ai au moins un objet, qui convient à ces exigences, mais queryset ne retourne rien. Tout suggère?

Répondre

2

Vous devez faire un filtrage en cascade, sinon la sélection actuelle retournera tous les produits qui ont "shop_product_categories"."category_id" avec la valeur de 1/2 et 4 et 6 en même temps ... Voici un exemple de jeu de requête qui retournera ce que vous voulez :

Product.objects.filter(categories__in=c[0:2]) 
       .filter(categories=c[2]) 
       .filter(categories=c[3]) 
       .distinct() 

qui génère SQL comme ceci:

SELECT DISTINCT "test1_product"."id" FROM "test1_product" INNER JOIN "test1_product_categories" ON ("test1_product"."id" = "test1_product_categories"."product_id") 
    INNER JOIN "test1_product_categories" T4 
     ON ("test1_product"."id" = T4."product_id") 
    INNER JOIN "test1_product_categories" T6 
     ON ("test1_product"."id" = T6."product_id") 
WHERE ("test1_product_categories"."category_id" IN (1, 2) 
    AND T4."category_id" = 3 
    AND T6."category_id" = 4) 
+0

Merci, cela fonctionne comme j'ai besoin! –