Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@method_decorator with login_required and permission_required

I'm using Class-based views where I would like to ensure that each view can be access by logged-in users and by one type of the users only (there are two groups of users - each group has different permissions).

I'm implementing this according to the docs with persmissions (I'm using Django 1.7.7) https://docs.djangoproject.com/en/1.7/topics/class-based-views/intro/#decorating-the-class, however using two parameters raises an error " method_decorator() takes exactly 1 argument (2 given)" .

Hence - how to do it such that those two factors(login and permissions) will be verified in a class-based view?

class PatientCreate(CreateView):
    model = Patient
    fields = '__all__'

    @method_decorator(login_required, permission_required('patient.session.can_add_patient'))
    def dispatch(self, *args, **kwargs):
        return super(PatientCreate, self).dispatch(*args, **kwargs)

Thanks!

like image 669
user1544500 Avatar asked Apr 16 '15 11:04

user1544500


1 Answers

In your case, permission_required will redirect to the login page for users that are not logged in, so you don't need to use login_required at all.

@method_decorator(permission_required('patient.session.can_add_patient')
def dispatch(self, *args, **kwargs):
    ...

If you really did need to use multiple decorators, then you can use a list in Django 1.9+

decorators = [other_decorator, permission_required('patient.session.can_add_patient')] 

class PatientCreate(CreateView):
    model = Patient
    fields = '__all__'

    @method_decorator(decorators)
    def dispatch(self, *args, **kwargs):
        ...

You can also shorten the code by decorating the class itself:

@method_decorator(decorators, name="dispatch")
class PatientCreate(CreateView):
    model = Patient
    fields = '__all__'

On Django 1.8 and earlier, you can't pass a list to method_decorator or decorate the class, so you have to stack the decorators

class PatientCreate(CreateView):
    model = Patient
    fields = '__all__'

    @method_decorator(other_decorator)
    @method_decorator(permission_required('patient.session.can_add_patient'))
    def dispatch(self, *args, **kwargs):
        ...

The decorators will process the request in the order they are passed to method_decorator. So for the examples above, other_decorator will run before permission_required.

like image 68
Alasdair Avatar answered Nov 15 '22 18:11

Alasdair