Python 创建表示查询集并集的查询集
假设我有以下模型:Python 创建表示查询集并集的查询集,python,django,django-orm,Python,Django,Django Orm,假设我有以下模型: 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
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)
假设我需要(尽管很奇怪)得到:
- 住在房子里或被称为“约翰”的人的名单
- 上述人员的车辆清单
找租户或约翰(房子)
从租户或约翰(房子)那里获得汽车。
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)
问题在于上述示例中重复了该逻辑。如果我可以获取获取租户或约翰(房屋)
以返回查询集
我可以将获取租户或约翰(房屋)的汽车定义为:
def get_cars_of_tenants_or_johns(house):
return Car.objects.filter(owner__in=get_tenants_or_johns(house))
为了做到这一点,get_tenants\u或_johns(house)
需要返回一个querysets的联合,而不将它们转换为其他集合
我不知道如何实现获取租户或约翰(房子)
,以便返回包含SQL联合的查询集。有办法吗?如果没有,是否有其他方法来实现我的目标?您提到了住在房子里的用户,但没有提到您的用户模型
我认为您确实需要仔细研究应用程序的结构——可能有更简单的方法来实现您的目标
但是为了回答您的问题,让我们设置三个助手函数。因为,正如我上面提到的,您没有概述您想要对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
,它是您可以迭代的所有匹配项的列表。您提到了住在房子里的用户,但没有提到您的用户模型
我认为您确实需要仔细研究应用程序的结构——可能有更简单的方法来实现您的目标
但是为了回答您的问题,让我们设置三个助手函数。因为,正如我上面提到的,您没有概述您想要对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
,它是您可以迭代的所有匹配项的列表。两个查询集上的|
操作符将返回表示联合的新查询集
函数需要更改为(去掉set()
wrappers):
所有操作都将按照需要进行。两个查询集上的
操作符将返回一个表示联合的新查询集
函数需要更改为(去掉set()
wrappers):
一切都将按照需要进行。感谢您的反馈。这是一个深夜的问题,我写了很多错字。我不是指用户对象,而是指个人对象。我已经修改了这个问题。不幸的是,你的建议租户+约翰
不起作用,尽管我非常希望它能起作用。它为+:“QuerySet”和“QuerySet”抛出一个不受支持的操作数类型。虽然我最初的问题听起来很傻,但它与我在职业上面临的问题类似(这更复杂,但需要类似的功能)。我希望它没有被否决,因为这是一个有效的问题。我编辑了我的帖子,使用itertoolschain
来组合查询集。请试一试。为了更深入地了解为什么/如何工作,我建议查看itertools文档和这篇文章:我已经找到了我想要的答案。它是查询集上的|
运算符。这正是我所需要的。对我来说,重要的是将上述函数返回的查询集作为查询集,而不是将它们转换为列表、集合或其他容器。这样,我就可以在这些查询集上调用.delete()
和.count()
。感谢您的反馈。这是一个深夜的问题,我写了很多错字。我不是指用户对象,而是指个人对象。我已经修改了这个问题。不幸的是,你的建议租户+约翰
不起作用,尽管我非常希望它能起作用。它为+:“QuerySet”和“QuerySet”抛出一个不受支持的操作数类型。虽然我最初的问题听起来很傻,但它与我在职业上面临的问题类似(这更复杂,但需要类似的功能)。我希望它没有被否决,因为这是一个有效的问题。我编辑了我的帖子,使用itertoolschain
来组合查询集。请试一试。为了更深入地了解为什么/如何工作,我建议查看itertools文档和这篇文章:我已经找到了我想要的答案。它是查询集上的|
运算符。这正是我所需要的。对我来说,重要的是将上述函数返回的查询集作为查询集,而不是将它们转换为列表、集合或其他容器。这样,我就可以对这些查询集调用.delete()
和.count()
。