构建具有动态字段数的 Django 优雅过滤器

Build a Django elegant filter with dynamic number of fields

我有一个 Django 模型,我正在为它做一个视图,过滤结果。

models.py:

Ingredient(models.Model):
    account = models.ForeignKey(Account, on_delete=models.CASCADE, null=False)
    brand = models.ForeignKey(Brand, on_delete=models.CASCADE, null=False)
    name = models.CharField(max_length=100, null=False, blank=False)
    cost = models.DecimalField(max_digits=14, decimal_places=2, null=False)

现在的重点是搜索表单(除了 account 之外的所有字段),其中 none 个字段是必需的,您可以仅按一个或两个字段进行过滤或者他们三个。

问题是我做不到:

Ingredient.objects.filter(account=account, brand=brand, name=name, cost=cost)

...因为可以发送品牌、名称和费用 empty/null

如何在不为每种过滤可能性制作过滤行代码的情况下解决这个问题?

我们可以创建一个效用函数来过滤掉 None。例如:

from django.db.models import Q

def filter_without_none(**kwargs):
    return Q(**{k: v for k, v in kwargs.items() if v is not None and v != ''})

现在我们可以过滤:

Ingredient.objects.filter(
    <b>filter_without_none(</b>account=account, brand=brand, name=name, cost=cost<b>)</b>
)

如果像 accountbrand、and/or name 这样的一个(或多个)值是 None,这些将 被考虑过滤。