Search code examples
pythondjangodjango-viewsdecoratorlogin-required

login_required decorator gives "object has no attribute 'user'" error


New to Django. I have a view that works well without @login_required decorator.

urls.py

urlpatterns = [
    path('play/', play.as_view(), name='play'),

view.py with @login_required commented out

from django.contrib.auth.decorators import login_required
.
.
class play(View):
    #@login_required
    def get(self, request, *args, **kwargs):
        print("GET request: ", request)
        return render(request, 'play.html', {})

**EDIT:**adding the setting.py entries

LOGIN_URL = 'home'
LOGIN_REDIRECT_URL = 'home'
LOGOUT_REDIRECT_URL = 'home'

The page load correctly in the browser and the request is printed on the console as follows

GET request:  <WSGIRequest: GET '/play/'>
[16/Aug/2021 23:17:23] "GET /play/ HTTP/1.1" 200 3591
[16/Aug/2021 23:17:23] "GET /static/css/home.css HTTP/1.1" 200 96
[16/Aug/2021 23:17:23] "GET /static/js/home.js HTTP/1.1" 200 3544
[16/Aug/2021 23:17:23] "GET /static/js/main.js HTTP/1.1" 200 1451443
[16/Aug/2021 23:17:23] "GET /static/images/BlankPicture.png HTTP/1.1" 200 16272
Not Found: /favicon.ico
[16/Aug/2021 23:17:24] "GET /favicon.ico HTTP/1.1" 404 7793

OTOH, if I uncomment the @login_required line, I get following error.

AttributeError at /play/
'play' object has no attribute 'user'
Request Method: GET
Request URL:    http://127.0.0.1:8000/play/
Django Version: 2.2.12
Exception Type: AttributeError
Exception Value:    
'play' object has no attribute 'user'
Exception Location: /usr/lib/python3/dist-packages/django/contrib/auth/decorators.py in _wrapped_view, line 20
Python Executable:  /usr/bin/python3
Python Version: 3.8.10
Python Path:    
['/home/<username>/workspace/djangoapp/src',
 '/usr/lib/python38.zip',
 '/usr/lib/python3.8',
 '/usr/lib/python3.8/lib-dynload',
 '/usr/local/lib/python3.8/dist-packages',
 '/usr/lib/python3/dist-packages']
Server time:    Mon, 16 Aug 2021 23:20:17 +0000

play.html is a vanilla html page with only static html in it. The error happens even if I am logged in on a different tab.

I see the error is happening in ....django/contrib/auth/decorators.py line 20

        @wraps(view_func)
        def _wrapped_view(request, *args, **kwargs):
            if test_func(request.user):   <<<Here is the error

In all the other views I check if the user is is_authenticated first and then use user.request successfully. I wanted to remove that if-else loop and simplify my views using @login_required decorator.

I am following the documentation here The login_required decorator Where is my mistake?

EDIT: I want to redirect the user to 'home' url if they are not logged in.


Solution

  • This error is because login_required is reading self(which is the play view object as described by the error) instead of request when used as a decorator for a view inside a class.

    Since this is a class-based view, login_required is used differently:

    from django.contrib.auth.decorators import login_required
    from django.utils.decorators import method_decorator
    
    
    @method_decorator(login_required, name='dispatch')
    class play(View):
        ...
    

    You can also use LoginRequiredMixin which works in a similar way:

    from django.contrib.auth.mixins import LoginRequiredMixin
    
    
    class play(LoginRequiredMixin, View):
        ...