对于我的项目,我需要动态创建自定义(类)方法。
我发现在 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':[]})}))
并消除了一个已经有点难以掌握的概念的复杂性。
您可能想了解元类。也许你可以覆盖一个类的新方法。我可以推荐你1或 2关于那个的帖子。
另一种选择是,也许您没有正确添加过滤器,或者以 django 不希望的方式添加过滤器?这可以解释为什么您没有收到任何错误,但没有调用任何函数。
关于python - 如何用python创建动态方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38575042/