在 Django 3 中,如何基于条件数组构建 AND 查询?
In Django 3, how do I build an AND query based on an array of conditions?
我正在使用 Python 3.8 和 Django 3。我有以下模型 ...
class Coop(models.Model):
objects = CoopManager()
name = models.CharField(max_length=250, null=False)
types = models.ManyToManyField(CoopType, blank=False)
addresses = models.ManyToManyField(Address)
enabled = models.BooleanField(default=True, null=False)
phone = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_phone')
email = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_email')
web_site = models.TextField()
我想构建一个高级搜索,我可以根据是否提供这些属性来搜索一个或多个属性。我有
class CoopManager(models.Manager):
def find(self, name, type, enabled):
if name:
qset = Coop.objects.filter(name=name)
if type:
qset = Coop.objects.filter(type__name=type)
if enabled:
qset = Coop.objects.filter(enabled=enabled)
return qset
但是上面是有缺陷的,因为它只会搜索一个属性。如何创建条件数组并将它们传递给我的查询?例如,如果提供了“enabled”和“name”,那么查询应该只搜索这两个东西。如果提供了“类型”和“名称”,我应该只搜索这两个东西。
您可以链接过滤器,从而在下一次过滤中使用可能已经被过滤的qset
:
class CoopManager(models.Manager):
def find(self, name<b>=None</b>, type<b>=None</b>, enabled<b>=None</b>):
<b>qset</b> = Coop.objects.all()
if name:
qset = <b>qset</b>.filter(name=name)
if type:
qset = <b>qset</b>.filter(type__name=type)
if enabled:
qset = <b>qset</b>.filter(enabled=enabled)
return qset
或者更方便,你可以做一个辅助函数:
def filter_qs_without_none(qs, **kwargs):
return qs.filter(<b>**{k: v for k, v in kwargs.items() if v is not None}</b>)
然后你可以过滤:
class CoopManager(models.Manager):
def find(self, name<b>=None</b>, type<b>=None</b>, enabled<b>=None</b>):
return <b>filter_qs_without_none(</b>
Coop.objects.all(),
name=name,
type__name=type,
enabled=enabled
<b>)</b>
我正在使用 Python 3.8 和 Django 3。我有以下模型 ...
class Coop(models.Model):
objects = CoopManager()
name = models.CharField(max_length=250, null=False)
types = models.ManyToManyField(CoopType, blank=False)
addresses = models.ManyToManyField(Address)
enabled = models.BooleanField(default=True, null=False)
phone = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_phone')
email = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_email')
web_site = models.TextField()
我想构建一个高级搜索,我可以根据是否提供这些属性来搜索一个或多个属性。我有
class CoopManager(models.Manager):
def find(self, name, type, enabled):
if name:
qset = Coop.objects.filter(name=name)
if type:
qset = Coop.objects.filter(type__name=type)
if enabled:
qset = Coop.objects.filter(enabled=enabled)
return qset
但是上面是有缺陷的,因为它只会搜索一个属性。如何创建条件数组并将它们传递给我的查询?例如,如果提供了“enabled”和“name”,那么查询应该只搜索这两个东西。如果提供了“类型”和“名称”,我应该只搜索这两个东西。
您可以链接过滤器,从而在下一次过滤中使用可能已经被过滤的qset
:
class CoopManager(models.Manager):
def find(self, name<b>=None</b>, type<b>=None</b>, enabled<b>=None</b>):
<b>qset</b> = Coop.objects.all()
if name:
qset = <b>qset</b>.filter(name=name)
if type:
qset = <b>qset</b>.filter(type__name=type)
if enabled:
qset = <b>qset</b>.filter(enabled=enabled)
return qset
或者更方便,你可以做一个辅助函数:
def filter_qs_without_none(qs, **kwargs):
return qs.filter(<b>**{k: v for k, v in kwargs.items() if v is not None}</b>)
然后你可以过滤:
class CoopManager(models.Manager):
def find(self, name<b>=None</b>, type<b>=None</b>, enabled<b>=None</b>):
return <b>filter_qs_without_none(</b>
Coop.objects.all(),
name=name,
type__name=type,
enabled=enabled
<b>)</b>