'Role' object has no attribute '__name__'
Asked Answered
S

2

5

I am trying to implement role based permission into my application. I have a decorator role_required into which I can pass a set of user roles and only those user with that role can access that view. I have properly assigned roles to the user but, now I am getting AttributeError stating that 'Role' object has no attribute '__name__'

views.py file:

m_role_required = method_decorator(role_required)
class AddProposal(FormView):

    @m_role_required(roles.space_admin)
    def dispatch(self, *args, **kwargs):
        return super(AddProposal, self).dispatch(*args, **kwargs)

The decorator role_required:

from django.contrib.auth.decorators import user_passes_test
def role_required(*roles):

    def check_role(user):
        return getattr(user, 'role', None) in roles
    return user_passes_test(check_role)

The Role class:

class Roles(object):
    _roles_dict = None

    @property
    def roles_dict(self):

        if self._roles_dict is None:
            self._roles_dict = {}
            for item in self._config:
                if isinstance(item, basestring):
                    # An item like 'manager'
                    self._roles_dict[item] = None
                else:
                    # Anything else
                    raise ImproperlyConfigured(_INCORRECT_ARGS)
        return self._roles_dict

    @property
    def choices(self):

        return [(role, role) for role in self.roles_dict.keys()]

    def __init__(self, config=None):

        self._config = config or getattr(settings, 'USER_ROLES', ())

    def __getattr__(self, name):

        if name in self.roles_dict.keys():
            return Role(name=name)
        else:
            raise AttributeError("No such role exists '%s'" % name)

roles = Roles()

I am not able to find out why this error is being raised. Can anyone help. Let me add the traceback with this,

Environment:

Request Method: GET
Request URL: http://127.0.0.1:8000/en-gb/spaces/bithin/proposal/add/


Traceback:

  48. class AddProposal(FormView):
File "/home/bithin/gsoc/week3/e-cidadania/src/apps/ecidadania/proposals/views.py" in AddProposal
  78.     @m_role_required(roles.space_admin)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _dec
  34.         update_wrapper(_wrapper, func)
File "/usr/lib/python2.7/functools.py" in update_wrapper
  33.         setattr(wrapper, attr, getattr(wrapped, attr))

Exception Type: AttributeError at /en-gb/spaces/bithin/proposal/add/
Exception Value: 'Role' object has no attribute '__name__'
Sorb answered 22/6, 2012 at 5:12 Comment(4)
Please post the full traceback, including the line numbers. You cannot debug the problem until you know exactly what code is causing it. An exception is not raised by "a class", it is raised by an individual line of code.Aeroplane
And where is Role class? Maybe it is just a typo?Legacy
Role class inside userrole from apps.thirdparty.userroles import rolesSorb
The problem appears to be in the role_required decorator, whose code you didn't post. Please try to cut down your post to include the code that's relevant to the error and not a bunch of extraneous code.Aeroplane
S
5

Have a look at the code for django.utils.decorators.method_decorator. The method decorator it returns cannot accept further parameters save for the actual function to decorate. Properties of this function, including its __name__, are copied over via functools.update_wrapper, in the usual Python fashion. You get this error because you pass a Role object instead of a function.

In other words, you need to rewrite your view like this:

space_admin_required = method_decorator(role_required(roles.space_admin))
class AddProposal(FormView):

    @space_admin_required
    def dispatch(self, *args, **kwargs):
        return super(AddProposal, self).dispatch(*args, **kwargs)
Sensualism answered 22/6, 2012 at 9:0 Comment(0)
C
9

This is a potential duplicate of Why do python instances have no __name__ attribute?

Short answer: the name of a class is stored in the class and is not directly available to the instance. You can access the class name of an instance via myinstance.__class__.__name__.

Calcium answered 25/11, 2013 at 22:44 Comment(1)
That post is about what a decorator expects, not about the classes' dictionary.Coadjutor
S
5

Have a look at the code for django.utils.decorators.method_decorator. The method decorator it returns cannot accept further parameters save for the actual function to decorate. Properties of this function, including its __name__, are copied over via functools.update_wrapper, in the usual Python fashion. You get this error because you pass a Role object instead of a function.

In other words, you need to rewrite your view like this:

space_admin_required = method_decorator(role_required(roles.space_admin))
class AddProposal(FormView):

    @space_admin_required
    def dispatch(self, *args, **kwargs):
        return super(AddProposal, self).dispatch(*args, **kwargs)
Sensualism answered 22/6, 2012 at 9:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.