我正在使用Django ORM来处理我的数据库查询。我有以下数据库表:
以及以下型号:
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查询?
答案 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