假设我有以下型号:
class House(models.Model):
address = models.CharField(max_length=255)
class Person(models.Model):
name = models.CharField(max_length=50)
home = models.ForeignKey(House, null=True, related_name='tenants')
class Car(models.Model):
make = models.CharField(max_length=50)
owner = models.ForeignKey(Person)
让我说我有需要(奇怪的,虽然)得到:
我想有两个功能:
get_tenants_or_johns(house)
get_cars_of_tenants_or_johns(house)
我可以将它们定义为:
from django.db.models.query_utils import Q
def get_cars_of_tenants_or_johns(house):
is_john = Q(owner__in=Person.objects.filter(name='John'))
is_tenant = Q(owner__in=house.tenants.all())
return Car.filter(is_john | is_tenant)
def get_tenants_or_johns(house):
johns = Person.objects.filter(name='John')
tenants = house.tenants.all()
return set(johns) | set(tenants)
问题是在上面的例子中重复了逻辑。如果我可以get_tenants_or_johns(house)
返回queryset
我可以将get_cars_of_tenants_or_johns(house)
定义为:
def get_cars_of_tenants_or_johns(house):
return Car.objects.filter(owner__in=get_tenants_or_johns(house))
为了做到这一点,get_tenants_or_johns(house)
需要返回查询集的并集,而不将它们转换为其他集合。
我无法弄清楚如何实现get_tenants_or_johns(house)
,以便返回包含SQL UNION
的查询集。有没有办法做到这一点?如果没有,是否有另一种方法来实现我想要做的事情?
答案 0 :(得分:3)
两个查询集上的|
运算符将返回表示联合的新查询集。
该函数需要更改为(摆脱set()
包装器):
def get_tenants_or_johns(house):
johns = Person.objects.filter(name='John')
tenants = house.tenants.all()
return johns | tenants
并且一切都将按照需要完成。
答案 1 :(得分:0)
您提到住在房子里的用户,但没有提及您的用户模型。
我认为你真的需要仔细研究你的应用程序的结构 - 可能有更简单的方法来实现你的目标。
但是要回答你的问题,让我们设置三个辅助函数。因为,正如我上面提到的,你没有概述你想用User类做什么 - 我假设将传递给这些函数的house
是一个地址:
helpers.py
def get_johns(house):
is_john = Person.objects.filter(name='John')
return is_john
def get_cars_of_tenants(house):
cars = Car.objects.filter(owner__home__address=house)
return cars
def get_tenants(house):
tenants = Person.objects.filter(home__address=house)
return tenants
现在,您可以为每个组合查询创建一个视图:
views.py:
import helpers.py
from itertools import chain
def get_cars_of_tenants_or_johns(request, house):
results = list(chain(get_cars_of_tenants(house), get_johns(house)))
return render_to_response('cars_or_johns.html', {"results": results,})
def get_tenants_or_johns(request, house):
results = list(chain(get_tenants(house), get_johns(house)))
return render_to_response('tenants_or_johns.html', {"results": results,})
这可以用于所有各种组合。返回的是results
,它是您可以迭代的所有匹配项的列表。