【问题标题】:Django - custom filter that calls a methodDjango - 调用方法的自定义过滤器
【发布时间】:2011-06-20 07:12:54
【问题描述】:

我知道您不能使用过滤器调用方法,因为它是基于数据库的。所以我正在尝试编写一个自定义过滤器。

    @staticmethod
    def custom_filter(obj,method_name, arg=False):
        for i in obj.objects.all():
            if getattr(i, method_name)() == arg:
                yield i

如果我打电话,我可以让它工作:

MyModel.custom_filter(MyModel,'my_method','myarg')

但是,我不能像常规过滤器那样将它们链接在一起。

我可以这样做:

@staticmethod
def custom_double_filter(obj,method1,arg1,method2,arg2):
    for i in obj.objects.all():
        if getattr(i, method1)() == arg1 and getattr(i,method2)()==arg2:
            yield i

但我希望它支持任意数量的过滤器,并且某些方法有自己的参数

@staticmethod
def custom_double_filter(obj,method1,arg1,method2,arg2):
    for i in obj.objects.all():
        if getattr(i, method1)(<may need to pass an argument>) == arg1 and getattr(i,method2)()==arg2:
            yield i

编辑:所以我尝试制作一个像这样的自定义管理器:

class GroupManager(models.Manager):
    use_for_related_fields = True

    def custom_filter(self,method_name, arg=False):
        results = []
        for i in self.all():
            if getattr(i, method_name)() == arg:
                results.append(i)
        return results

这适用于对 custom_filter 的一次调用,但显然由于我要返回一个列表,因此我无法将这些调用链接在一起。我需要一种能够传递任意数量参数的方法

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

    过滤器实际上并不是模型类的一部分。

    它们是与您的 Model 类关联的 Manager 的一部分。默认管理器实例名为objects

    但是,您可以使用精美的过滤器添加经理。

    http://docs.djangoproject.com/en/1.2/topics/db/managers/

    当您编写自己的自定义管理器时,请务必阅读此部分:http://docs.djangoproject.com/en/1.2/topics/db/managers/#controlling-automatic-manager-types,以便您的新管理器执行默认管理器所做的所有操作,以及您的新奇特过滤器。

    我希望过滤器能够调用任何方法或方法组合

    这有点疯狂,但你也许可以让它发挥作用。调用“任何方法”意味着您必须准备所有必需的参数并将其传递给该方法函数。对于我的口味,它开始涉及太多 *arg**kw 元编程。

    我建议管理器不是“通用的”,而是管理器中的方法——特别是——匹配底层模型。你也不会打电话给他们filter。您将以一种简单的方式将它们映射到模型。

    我认为映射到简单模型方法的简单管理器方法是最好的方法。

    此外,您还拥有良好的老式 Python 列表推导和生成器函数。我们用这个。

    def our_special_filter( some_queryset ):
        for row in some_queryset:
            if row.aMethod(): yield row
    
    result= our_special_filter( SomeModel.objects.filter(...) )
    

    是的。它打破了流畅的 API 风格。但这很简单,而且效果很好。

    【讨论】:

    • 这看起来像是我可能想要放置过滤器的地方。不过,我将如何编写实际的过滤器?我希望过滤器能够调用任何方法或方法组合
    • 是否可以让某些东西返回一个查询集?如果是这样,我可以将过滤器链接在一起。
    • @JPC:“让某些东西返回一个查询集?”不容易。 “因为它是基于数据库的”。没有必要。您可以更轻松地在 QuerySet 的 filter().filter() fluent API 样式之外添加过滤器。
    猜你喜欢
    • 1970-01-01
    • 2016-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    • 2021-06-21
    • 2014-02-14
    • 1970-01-01
    相关资源
    最近更新 更多