Django高级查询

时间:2012-10-30 12:45:36

标签: python sql django

我正在使用Django ORM来处理我的数据库查询。我有以下数据库表:

  • 资源
  • 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)

目前,我需要查询一组预留中使用的资源。我使用以下查询:

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查询?

2 个答案:

答案 0 :(得分: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))

答案 1 :(得分: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