【问题标题】:Build a Django elegant filter with dynamic number of fields构建具有动态字段数的 Django 优雅过滤器
【发布时间】:2020-06-14 03:35:22
【问题描述】:

我有一个 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 之外的所有字段都有),它的任何字段都不是必需的,您可以仅按单个字段或两个或三个字段进行过滤。

问题是我做不到:

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

...因为品牌、名称和成本可以发送为空/null

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

【问题讨论】:

    标签: python django filter django-queryset


    【解决方案1】:

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

    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(
        filter_without_none(account=account, brand=brand, name=name, cost=cost)
    )

    如果accountbrand 和/或name 等值中的一个(或多个)是None,则在过滤时不会考虑这些值。 p>

    【讨论】:

    • 哇,这是一个优雅的 Python 代码。谢谢!但我收到以下错误:ValueError at /Ingredient/filter_byField 'id' expected a number but got ''.The above exception (invalid literal for int() with base 10: '') was the direct cause of the following exception:。我不明白为什么它还试图过滤字段 id(它没有在我的模型中声明,但它当然是在 db 表中)。
    • @GonzaloDambra:啊,但那不是None,那是空字符串。你能用错误的traceback编辑你的问题吗?
    • 成功了!我刚刚将and v is not '' 添加到filter_without_none 方法中。你是对的,那是一个空字符串,而不是 None !谢谢。
    • @GonzaloDambra:小评论:我会使用!= ''。通常空字符串确实是“缓存”的。但最好是安全而不是抱歉:)。
    猜你喜欢
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 2018-07-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多