Django - 调用方法的自定义过滤器

时间:2011-02-02 21:53:38

标签: python django django-models

我知道您无法使用过滤器调用方法,因为它基于数据库执行此操作。所以我正在尝试编写自定义过滤器。

    @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的一次调用,但很明显,因为我正在返回一个列表,所以我无法将这些调用链接在一起。我需要一种方法来传递任意数量的参数

1 个答案:

答案 0 :(得分:5)

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

他们是与您的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风格。但它很简单,效果很好。