Hi,

as of today, adding a permission_required and / or a login_required 
decorator on a class based view is a bit ugly, as you have to decorate the 
dispatch method, which you then have to write down in your class.
On top of that, you can't directly use the decorator itself, as you have to 
wrap it in the method_decorator decorator so it can be applied to a class 
method instead of a free running function.

The problem is that none of those things you have to do in order to use the 
permission_required and / or login_required decorator are linked to 
permission / login logic. It's needed only because there's not a proper 
place to put those decorator, and you can't use them as class decorator.

Another problem is that some people might find it a bit weird, and only 
apply those decorator to a specific method, like get or post, which, if it 
works, isn't covering other method and might become an issue. It's also not 
consistent with the function based decorator which cover any http methods 
at once.

In our team, we refactored it a little bit so we could use a class 
decorator instead. It is much more consistent with the function based view 
logic, and requires much less code to implement.

for the permission_required, it looks like that:
```
from django.contrib.auth.decorators import permission_required as pr
from django.utils.decorators import method_decorator


def method_permission_decorator(permission, login_url):
    return method_decorator(pr(permission, login_url=login_url))

def permission_required(permission, login_url="/admin/login"):
    # build the specific permissions to use
    specific_permissions = method_permission_decorator(permission, 
login_url)
    def wrapper(cls):
        # decorate the dispatch method with the specific permissions we set
        cls.dispatch = specific_permissions(cls.dispatch)
        return cls
    return wrapper
```

This is specific to our needs of course, but I think it's easy to make more 
generic, and would add value other teams could benefit from.

What it allows is to replace :

```
class MyView(View):
    # my code here
    @method_decorator(permission_required(perm))
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)
```

by this

```
@permission_required(perm)
class MyView(View):
    # my code here

```

Now, idk if it would make more sense to have another decorator 
class_permission_required or to have the permission_required decorator 
tweaked to work with class too, but no matter what's best on that regard, i 
think it would be a valuable change.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/9529f8c7-e6b4-48e0-8941-efb0123cd5d2n%40googlegroups.com.
  • add... Martin Milon
    • ... Albert
      • ... 'Adam Johnson' via Django developers (Contributions to Django itself)
        • ... Martin Milon
          • ... 'Adam Johnson' via Django developers (Contributions to Django itself)

Reply via email to