2010-10-21 11 views
19

VE nesnesini Q nesnelerini kullanarak bir süzgeçte birleştirmeyi denerim. Bu gibi görünüyor | bir AND gibi davran. Bu, bir alt sorgu olarak değil, aynı sorguda çalıştırılan önceki ek açıklama ile ilgilidir.S ve AND nesnelerinin birlikte Q nesnelerini birleştiren Django sorgu süzgeci, beklenen sonuçları döndürmez

Bunu Django ile işlemenin doğru yolu nedir?

models.py

class Type(models.Model): 
    name = models.CharField(_('name'), max_length=100) 
    stock = models.BooleanField(_('in stock'), default=True) 
    hide = models.BooleanField(_('hide'), default=False) 
    deleted = models.BooleanField(_('deleted'), default=False) 

class Item(models.Model): 
    barcode = models.CharField(_('barcode'), max_length=100, blank=True) 
    quantity = models.IntegerField(_('quantity'), default=1) 
    type = models.ForeignKey('Type', related_name='items', verbose_name=_('type')) 

views.py

def hire(request): 
    categories_list = Category.objects.all().order_by('sorting') 
    types_list = Type.objects.annotate(quantity=Sum('items__quantity')).filter(
     Q(hide=False) & Q(deleted=False), 
     Q(stock=False) | Q(quantity__gte=1)) 
    return render_to_response('equipment/hire.html', { 
      'categories_list': categories_list, 
      'types_list': types_list, 
      }, context_instance=RequestContext(request)) 

elde edilen SQL sorgusu

SELECT "equipment_type"."id" [...] FROM "equipment_type" LEFT OUTER JOIN 
    "equipment_subcategory" ON ("equipment_type"."subcategory_id" = 
    "equipment_subcategory"."id") LEFT OUTER JOIN "equipment_item" ON 
    ("equipment_type"."id" = "equipment_item"."type_id") WHERE 
    ("equipment_type"."hide" = False AND "equipment_type"."deleted" = False) 
    AND ("equipment_type"."stock" = False)) GROUP BY "equipment_type"."id" 
    [...] HAVING SUM("equipment_item"."quantity") >= 1 

beklenen SQL sorgusu

SELECT 
    * 
FROM 
    equipment_type 
LEFT JOIN (
    SELECT type_id, SUM(quantity) AS qty 
    FROM equipment_item 
    GROUP BY type_id 
) T1 
ON id = T1.type_id 
WHERE hide=0 AND deleted=0 AND (T1.qty > 0 OR stock=0) 

DÜZENLEME: Ben açıkça gruplandırma belirtmek için parantez ekleyerek

+0

bana yapılan bir hata gibi görünüyor benzer bir şey üretecektir. Bir hata raporu gönderirim ya da #django – tback

cevap

4

Tamam burada, hayır başarı: | o zaman bu çalışması gerekir

[...].filter(
    Q(hide=False) & Q(deleted=False), 
    Q(stock=False) | Q(quantity__gte=1)) 

sen (A & B) & (D C) isteseydi:

Başlangıçta süzgecin bu vardı veya #django’da. Bu yüzden ... Bu sorunu çözmek için bir ham SQL sorgusu kullanmayı tercih İşte çalışma kodu

:

types_list = Type.objects.raw('SELECT * FROM equipment_type 
    LEFT JOIN (           
     SELECT type_id, SUM(quantity) AS qty    
     FROM equipment_item         
     GROUP BY type_id         
    ) T1             
    ON id = T1.type_id          
    WHERE hide=0 AND deleted=0 AND (T1.qty > 0 OR stock=0) 
    ') 
20

deneyin (equipment_subcategory üzerinden birleştirmek olmadan) beklenen SQL sorgusu eklendi? Daha önce de belirttiğiniz gibi, filter()'a giden çoklu parametreler, yalnızca alttaki SQL'de AND aracılığıyla birleştirilir.

[...].filter(
    Q(hide=False) & Q(deleted=False) & 
    (Q(stock=False) | Q(quantity__gte=1))) 
+0

numaralı telefonu sorardım. Bu çözümü denedim, ancak yine de isteği doğru şekilde ele almıyor. Http://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-objects adresindeki dokümantasyon, filtre (Q & Q) .filter (Q | Q) veya filtre (Q & Q) dikkate alınmalıdır. , Q | Q) veya filtre (Q & Q & (Q | Q)) hepsi aynı şekilde davranmalıdır. Ve benim durumum, yanlış yol ... – cgaspoz

+0

Annotate() ile eklenmeyen bir şeyle denediniz mi? Filter() ve exclude() için AND ve OR mantığı belgelerinin kurşun geçirmez olmaması nedeniyle gerçek sorguları denetlemeye devam edin. Belgeler SQL'de OR'd cümlelerini gösterir ancak bunu 1.2.3 ve sqlite3 ile görmüyorum. Qa & Qb & Qc (Qc | Qd) yaptığımda görüyorum. – istruble

4

Bu cevap geç ama orada adamlar bir çok yararlı olabilir.

[...].filter(hide=False & deleted=False) 
.filter(Q(stock=False) | Q(quantity__gte=1)) 

Bu

WHERE (hide=0 AND deleted=0 AND (T1.qty > 0 OR stock=0))