Hahan't
Hahan't

Reputation: 487

Set methods with decorators dynamically

I have this class:

class SomeMixin:
    permissions = (SomePermission,)
    methods = ('GET',)

    @list_route(methods=methods, url_path='en', permission_classes=permissions)
    def en_list(self):
        return get_translated_objects(self, 'en')

    @list_route(methods=methods, url_path='ru', permission_classes=permissions)
    def ru_list(self):
        return get_translated_objects(self, 'ru')

    @detail_route(methods=methods, url_path='en', permission_classes=permissions)
    def en_detail(self):
        return get_translated_object(self.get_object(), 'en')

    @detail_route(methods=methods, url_path='ru', permission_classes=permissions)
    def ru_detail(self):
        return get_translated_object(self.get_object(), 'ru')

I can have more languages in the future and it's not a good solution.
I thought to create loop of languages list and add methods to the class with setattr(self, func_name, func), like:

langs = ('en', 'ru')
for lang in langs:
    setattr(self, func.__name__, func)

But I should add decorators to every method, how can I do it?

Upvotes: 1

Views: 95

Answers (1)

Nitul
Nitul

Reputation: 379

I believe you should be able to patch the contents of this example into your code. That being said, it seems like a better approach to detect the language from the http header and return an appropriate response. This approach though functional is not the cleanest.

# This decorator is meant to simulate the decorator exposed by django
def route(url, language, method):
    def wrapper(func):
        def inner(*args, **kwargs):
            print('url => {0}'.format(url))
            print('language => {0}'.format(language))
            print('method => {0}'.format(method))
            func(*args, **kwargs)
        return inner
    return wrapper


# This class is analogous to your SomeMixin class
class foo(object):
    def __init__(self):
        method = 'GET'
        # fields holds the parameters that will change for each method like url
        # and language
        fields = (('en', '/en', 'en_list'), ('ru', '/ru', 'ru_list'))
        for lang, url, func_name in fields:
            setattr(self, func_name, route(url=url, language=lang, method=method)(self.func_creator(lang)))


    def func_creator(self, language):
        def inner():
            print('hello in {0}'.format(language))
        return inner


def main():
    foo_instance = foo()
    print('Calling foo.en_list()')
    foo_instance.en_list()

    print()

    print('Calling foo.ru_list()')
    foo_instance.ru_list()


if __name__ == '__main__':
    main()

Upvotes: 1

Related Questions