python - 如何用python创建动态方法?

标签 python django

对于我的项目,我需要动态创建自定义(类)方法。

我发现在 Python 中并不那么容易:

class UserFilter(django_filters.FilterSet):
    '''
    This filter is used in the API
    '''
    # legacy below, this has to be added dynamically
    #is_field_type1 = MethodFilter(action='filter_field_type1') 

    #def filter_field_type1(self, queryset, value):
    #    return queryset.filter(related_field__field_type1=value)

    class Meta:
        model = get_user_model()
        fields = []

但它给我错误(和头痛...)。这可能吗?

我尝试使#legacy 之间的代码动态化

我发现一个方法是动态创建类

def create_filter_dict():
    new_dict = {}
    for field in list_of_fields:

        def func(queryset, value):
            _filter = {'stableuser__'+field:value}
            return queryset.filter(**_filter)

        new_dict.update({'filter_'+field: func})

        new_dict.update({'is_'+field: MethodFilter(action='filter_'+field)})

    return new_dict


meta_model_dict = {'model': get_user_model(), 'fields':[]}
meta_type = type('Meta',(), meta_model_dict)

filter_dict = create_filter_dict()
filter_dict['Meta'] = meta_type
UserFilter = type('UserFilter', (django_filters.FilterSet,), filter_dict)

但是,这给了我

TypeError at /api/v2/users/
func() takes 2 positional arguments but 3 were given

有谁知道如何解决这个难题?

最佳答案

Exception Value: 'UserFilter' object has no attribute 'is_bound'

您收到此错误是因为您正在生成的类方法未绑定(bind)到任何类。要将它们绑定(bind)到类,您需要使用 setattr()

在控制台上试试这个:

class MyClass(object):
    pass

@classmethod 
def unbound(cls):
    print "Now I'm bound to ", cls


print unbound
setattr(MyClass, "bound", unbound) 
print MyClass.bound 
print MyClass.bound()

Traceback: UserFilter = type('Foo', (django_filters.FilterSet, ), create_filter_dict().update({'Meta':type('Meta',(), {'model': get_user_model(), 'fields':[]} )})) TypeError: type() argument 3 must be dict, not None

现在,这是失败的,因为 dict.update() 不返回相同的实例,返回 None。这很容易修复

class_dict = create_filter_dict()
class_dict.update({'Meta':type('Meta',(), {'model': get_user_model(), 'fields':[]})}
UserFilter = type('Foo', (django_filters.FilterSet, ), class_dict))

但是,看看代码看起来有多乱。我建议你尝试成为 使您编写的代码更加清晰,即使它需要多写几行。从长远来看,您和您的团队的代码将更易于维护。

meta_model_dict = {'model': get_user_model(), 'fields':[]}
meta_type = type('Meta',(), meta_model_dict)

filter_dict = create_filter_dict()
filter_dict['Meta'] = meta_type
UserFilter = type('Foo', (django_filters.FilterSet,), filter_dict)

此代码可能并不完美,但比您发布的原始代码行更具可读性:

UserFilter = type('Foo', (django_filters.FilterSet, ), create_filter_dict().update({'Meta':type('Meta',(), {'model': get_user_model(), 'fields':[]})}))

并消除了一个已经有点难以掌握的概念的复杂性。

您可能想了解元类。也许你可以覆盖一个类的方法。我可以推荐你12关于那个的帖子。

另一种选择是,也许您没有正确添加过滤器,或者以 django 不希望的方式添加过滤器?这可以解释为什么您没有收到任何错误,但没有调用任何函数。

关于python - 如何用python创建动态方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38575042/

相关文章:

Python,JSON 如何检查用户选择的时间是否尚未被其他人预订?

jquery - 当值有空格时输入隐藏值属性

python - 对 python 列表的子集进行排序,使其具有与其他列表中相同的相对顺序

django - Django中由多个IntegerRangeField组成的选择字段

python - Django Forms 无法呈现单选按钮

python - 在封闭范围内赋值之前引用变量 p

python - Dataframe - 获取最常见的值及其计数

javascript - 填写表格后替换两个变量

mysql - 逆向工程 mysql 数据库以创建 django 应用程序

python - 如何在 View 中访问 pk (Django)