2012-10-30 109 views
2

我正在使用Django ORM來處理我的數據庫查詢。我有以下的數據庫表:Django高級查詢

  • 資源
  • resource_pool
  • resource_pool_elem
  • 預訂

及以下車型:

class Resource(models.Model): 

    name = models.CharField(max_length=200) 

class Reservation(models.Model): 
    pass 

class ResourcePool(models.Model): 

    reservation = models.ForeignKey(Reservation, related_name="pools", db_column="reservation") 
    resources = models.ManyToManyField(Resource, through="ResourcePoolElem") 
    mode = models.IntegerField() 

class ResourcePoolElem(models.Model): 

    resPool = models.ForeignKey(ResourcePool) 
    resource = models.ForeignKey(Resource) 

目前,我需要查詢在一組rese中使用的資源rvations。我用下面的查詢:

resourcesNames = [] 
reservations = [] 
resources = models.Resource.objects.filter(
    name__in=resourcesNames, resPool__reservation__in=reservations).all() 

,我認爲比賽對類似這樣的一個SQL查詢:

select * 
from resource r join resource_pool rp join resource_pool_elem rpe join reservation reserv 
where r.id = rpe.resource and 
    rpe.pool = rp.id and 
    reserv.id = rp.reservation and 
    r.name in (resourcesNames[0], ..., resourcesNames[n-1]) 
    reserv.id in (reservations[0], ..., reservations[n-1]) 

現在,我想一個限制添加到該查詢。每個池可能有一個獨佔模式布爾標誌。將有一個額外的輸入列表,每個池請求的獨佔標誌,我只想查詢獨佔標誌匹配請求的專有標誌,如果exclusive = true或獨佔標誌爲false的池的資源的資源。我可以使用Python構建SQL查詢,其代碼類似於:

query = "select * 
    from resource r join resource_pool rp join resource_pool_elem rep 
    join reservation reserv 
    where r.id = rpe.resource and 
    rpe.pool = rp.id and 
    reserv.id = rp.reservation and 
    reserv.id in (reservations[0], ..., reservations[n-1]) and (" 
for i in resourcesNames[0:len(resourcesNames)] 
    if i > 0: 
     query += " or " 
    query += "r.name = " + resourcesNames[i] 
    if (exclusive[i])  
     query += " and p.mode == 0" 
query += ")"  

有沒有一種方法可以在Django查詢中表達這個sql查詢?

回答

3

也許你可以用Q objects做到這一點。我有一些問題圍繞着你的例子,但讓我們用一個更簡單的模型來看看它。

class Garage(models.Model): 
    name  = models.CharField() 

class Vehicle(models.Model): 
    wheels = models.IntegerField() 
    gears = models.IntegerField() 
    garage = models.ForeignKey(Garage) 

說你想在車庫裏所有的「多輪」的車輛(例如,所有的摩托車和汽車,但沒有單輪腳踏車),但對於汽車,你只希望那些有CVT變速器,不僅意味着他們有一個單一的齒輪。 (這是怎麼了,不知道,但包涵...;)以下應該給你的是:

from django.db.models import Q 
garage = Garage.objects.all()[0] 
query = Vehicle.objects.filter(Q(garage=garage)) 
query = query.filter(Q(wheels=2) | (Q(wheels=4) & Q(gears=1))) 

鑑於以下可用數據:

for v in Vehicle.objects.filter(garage=garage): 
    print 'Wheels: {}, Gears: {}'.format(v.wheels, v.gears) 

Wheels: 1, Gears: 1 
Wheels: 2, Gears: 4 
Wheels: 2, Gears: 5 
Wheels: 4, Gears: 1 
Wheels: 4, Gears: 5 

運行查詢會給我們:

for v in query: 
    print 'Wheels: {}, Gears: {}'.format(v.wheels, v.gears) 

Wheels: 2, Gears: 4 
Wheels: 2, Gears: 5 
Wheels: 4, Gears: 1 

最後,以使其適應你的情況,你也許可以大致如下使用的東西:

query = models.Resource.objects.filter(Q(resPool__reservation__in=reservations)) 
query = query.filter(Q(name__in(resourcesNames)) 
query = query.filter(Q(resPool__exclusive=True) & Q(resPool__mode=0)) 
0

你可以使用Django的光標進行查詢,例如

看到文檔: https://docs.djangoproject.com/en/dev/topics/db/sql/

from django.db import connection 

def my_custom_sql(self): 
    cursor = connection.cursor() 

    cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz]) 

    cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz]) 
    row = cursor.fetchone() 

    return row