Home > Software engineering >  Django : How write a decorator that takes an input after a redirect function
Django : How write a decorator that takes an input after a redirect function

Time:03-28

I want to write a decorator that takes an input coming from a redirect function (the value : id_contrat). If I explain a little bit more. An user selects a value in a form, then this value is redirect to another view "home". I want to check that the user has the rights on this value ! So I need to get it in my decorator. How do I add this value to my decorator.

I tried something but it is not working : `TypeError: wrapper_func() got an unexpected keyword argument 'id_contrat'`

My views :

@authenticated_user
def selectcontrat(request) :

    context = initialize_context(request)
    form_client = SelectClient(request.POST, user=request.user)
    if form_client.is_valid():
        id_contrat = request.POST.get("ID_Customer")
    
        return redirect(reverse('home', args=(id_contrat,)))

    context['form_client'] = form_client

    return render(request, 'base/selectcontrat.html', context)


@authenticated_user
@check_user_rights
def home(request, id_contrat=None):
    context = initialize_context(request)

    return render(request, 'home.html', context)

the url definition :

from django.urls import path
from . import views

urlpatterns = [
    path('home/<int:id_contrat>/', views.home, name="home"),
    path('', views.loginAD, name="login"),
    path('signin', views.sign_in, name='signin'),
    path('callback', views.callback, name='callback'),
    path('selectcontrat', views.selectcontrat, name='selectcontrat')

the form :

class SelectClient(forms.Form):

    ID_Customer = forms.ChoiceField(label="Company :")  
        
    
    def __init__(self, *args, **kwargs) :
        self.user = kwargs.pop('user')
        super(SelectClient, self).__init__(*args, **kwargs)

        id_client_list = AADJNTGroup.objects.filter(ID_User_id=self.user.id).values_list('ID_Group_id', flat=True)
        id_client_list = list(id_client_list)

        client_choices = Groups.objects.all().filter(ID__in=id_client_list).values_list('IDCustomer','GroupName')
        
        self.fields['ID_Customer'].choices = client_choices

          

Edited :the decorator

def check_user_rights(id_contrat) :

def wrapper_func(view_func) :
    @wraps(view_func)
    def wrapper(request, *args, **kwargs) :
        print(kwargs["id_contrat"])
        return view_func(request, *args, **kwargs)
    return wrapper
return wrapper_func
        

CodePudding user response:

You should remove the id_contrat argument from your decorator unless you plan on passing this argument when decorating your view for example @check_user_rights(my_id_contrat)

def check_user_rights():
    def wrapper_func(view_func):
        @wraps(view_func)
        def wrapper(request, *args, **kwargs):
            # This prints all the keyword arguments passed to your view
            # and should contain id_contrat from your url
            print(kwargs)
            return view_func(request, *args, **kwargs)
        return wrapper
    return wrapper_func

@check_user_rights()
def home(request, id_contrat=None):
    context = initialize_context(request)
    return render(request, 'home.html', context)

You also might find some value in the comments of the answer to Having trouble making a custom django view decorator (with args)

  • Related