Access request user and url parameters in django decorator

Question:

I am trying to eliminate redundant code by creating a decorator to handle simple logic that is always repeated. Basically every view I create has the following logic to check if a user is in a class.

@login_required
def view(request, class_id):

    class_ = UserClasses.objects.get(user=request.user, class_id=class_id)

    # if the user is in the class
    if class_:

I’d like to do the following:

View:

@user_passes_test(in_class(request.user, class_id))
@login_required
def view(request, class_id):

Decorator:

from apps.classes.models import UserClasses

def in_class(request, class_id):
    class_ = UserClasses.objects.get(user=request.user, class_id=class_id)
    if class_:
        return true
    else:
        return false

What’s the best way to go about achieving this?

Asked By: Sam Munroe

||

Answers:

Your decorator should be like this

def user_passes_test(old_fuction):
    def new_function(request, class_id, *args, **kwargs):
        try:
            class_ = UserClasses.objects.get(user=request.user, class_id=class_id)
        except Exception as e:
            return HttpResponse('ERROR: User not present in the class')
        return old_fuction(request, class_id, *args, **kwargs)
    return new_function

If the UserClasses contains row with both user and class_id(assumes that user is unique), the view function will be executed.Otherwise it will return an Error response(ERROR: User not present in the class).

And you view function should be

@user_passes_test
@login_required
def view(request, class_id):

if you want the class_ object in the view function, you can do it by simple changes. modify your decorator like

def user_passes_test(old_fuction):
    def new_function(request, class_id, *args, **kwargs):
        try:
            class_ = UserClasses.objects.get(user=request.user, class_id=class_id)
        except Exception as e:
            return HttpResponse('ERROR: User not present in the class')
        return old_fuction(request, class_id, class_, *args, **kwargs)
    return new_function

And the view function should be

@user_passes_test
@login_required
def view(request, class_id, class_obj):

where class_obj contains the class_ object

Answered By: Aneesh R S