Search code examples
pythondjangodecoratorpython-decorators

Access request user and url parameters in django decorator


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?


Solution

  • 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