[Django] #16626: login_required attribute in class-based Generic Views

7 views
Skip to first unread message

Django

unread,
Aug 12, 2011, 7:17:26 PM8/12/11
to django-...@googlegroups.com
#16626: login_required attribute in class-based Generic Views
-------------------------------------------------+-------------------------
Reporter: szczav | Owner: nobody
Type: New feature | Status: new
Milestone: | Component: Generic
Version: SVN | views
Keywords: login_required decorator view | Severity: Normal
generic views | Triage Stage:
Has patch: 1 | Unreviewed
UI/UX: 0 | Easy pickings: 0
-------------------------------------------------+-------------------------
Current generic views implementation allows for using login_required
decorator in two ways:
1. By using decorator in urls:
{{{
#!python
login_required(MyView.as_view())
}}}
2. By overriding dispatch method:
{{{
#!python
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(self.__class__, self).dispatch(request, *args,
**kwargs)
}}}

First way doesn't allow for subclassing decorated view and is ugly because
separates part of class logic into separate file. Second way is also ugly
- it makes you override dispatch() method in every place where you want to
use one, simple decorator. It's especially annoying on websites which have
a lot of content visible only for signed users. It's unpleasant to read
and violates DRY. The best solution to this problem is creating
login_required class attribute for all generic views. It'd work for all
generic views this way:
{{{
#!python
class MyView(TemplateView):
login_required = True
template_name = 'some_template.html'
}}}
Patch attached.

--
Ticket URL: <https://code.djangoproject.com/ticket/16626>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Aug 13, 2011, 4:58:10 PM8/13/11
to django-...@googlegroups.com
#16626: login_required attribute in class-based Generic Views
-------------------------------------+-------------------------------------
Reporter: szczav | Owner: nobody
Type: New | Status: closed
feature | Component: Generic views
Milestone: | Severity: Normal
Version: SVN | Keywords: login_required
Resolution: | decorator view generic views
worksforme | Has patch: 1
Triage Stage: | Needs tests: 0
Unreviewed | Easy pickings: 0
Needs documentation: 0 |
Patch needs improvement: 0 |
UI/UX: 0 |
-------------------------------------+-------------------------------------
Changes (by aaugustin):

* status: new => closed
* needs_better_patch: => 0
* resolution: => worksforme
* needs_tests: => 0
* needs_docs: => 0


Comment:

I'm not in favor of tying the generic views to the auth framework. If we
add a special case for `login_required`, the next question is obviously
going to be about `permission_required('foo.bar')`. Clearly, it isn't
desireable to duplicate the auth API in the generic views.

What about defining your view like this:
{{{
class MyView(...):
# this is a generic view
...

my_view = login_required(MyView.as_view())
}}}
and using `my_view` in your URLconf?

If you have many generic views that should be decorated with login
required, an alternative is to implement a mixin, like this:
{{{
class LoginRequiredMixin(object):
def as_view(cls):
return login_required(super(LoginRequiredMixin, cls).as_view())

class MyView(LoginRequiredMixin, ...):
# this is a generic view
...
}}}
and use `MyView.as_view()` is your URLconf.

--
Ticket URL: <https://code.djangoproject.com/ticket/16626#comment:1>

Django

unread,
Apr 22, 2013, 5:05:37 AM4/22/13
to django-...@googlegroups.com
#16626: login_required attribute in class-based Generic Views
-------------------------------------+-------------------------------------
Reporter: szczav | Owner: nobody
Type: New feature | Status: closed
Component: Generic views | Version: master
Severity: Normal | Resolution:
Keywords: login_required | worksforme
decorator view generic views | Triage Stage:
Has patch: 1 | Unreviewed
Needs tests: 0 | Needs documentation: 0
Easy pickings: 0 | Patch needs improvement: 0
| UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by xhannan):

I have been trying to implement the LoginRequiredMixin class the way it is
shown above, but running into some issues. Here is the error message I
get --

"unbound method as_view() must be called with HomeView instance as first
argument (got nothing instead)"

I have implemented (rather copied and pasted) the LoginRequiredMixin
class. Here is the code --

{{{
from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView

class LoginRequiredMixin(object):
def as_view(cls):
return login_required(super(LoginRequiredMixin, cls).as_view())

class HomeView(LoginRequiredMixin, TemplateView):
template_name = 'web/home.html'
}}}

Here is my urls.py file --

{{{
from django.conf.urls import patterns, url
from web.views import *

urlpatterns = patterns('web',
url(r'^$', HomeView.as_view(), name='web-home'),
url(r'^login/$', LoginView.as_view(), name='web-
login'),
)

}}}

Here is the complete error message on browser --

{{{
TypeError at /web/
unbound method as_view() must be called with HomeView instance as first
argument (got nothing instead)
Request Method: GET
Request URL: http://127.0.0.1:8000/web/
Django Version: 1.5.1
Exception Type: TypeError
Exception Value:
unbound method as_view() must be called with HomeView instance as first
argument (got nothing instead)
Exception Location: /Users/khan/PycharmProjects/DjangoTest/web/urls.py
in <module>, line 5
Python Executable: /Users/khan/virtuanenvs/django-test-env/bin/python
Python Version: 2.7.4
Python Path:
['/Users/khan/PycharmProjects/DjangoTest',
'/Applications/PyCharm.app/helpers/pydev',
'/Users/khan/PycharmProjects/DjangoTest',
'/Users/khan/virtuanenvs/django-test-env/lib/python27.zip',
'/Users/khan/virtuanenvs/django-test-env/lib/python2.7',
'/Users/khan/virtuanenvs/django-test-env/lib/python2.7/plat-darwin',
'/Users/khan/virtuanenvs/django-test-env/lib/python2.7/plat-mac',
'/Users/khan/virtuanenvs/django-test-env/lib/python2.7/plat-mac/lib-
scriptpackages',
'/Users/khan/virtuanenvs/django-test-env/lib/python2.7/lib-tk',
'/Users/khan/virtuanenvs/django-test-env/lib/python2.7/lib-old',
'/Users/khan/virtuanenvs/django-test-env/lib/python2.7/lib-dynload',
'/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
'/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-
darwin',
'/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
'/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-
mac',
'/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac
/lib-scriptpackages',
'/Users/khan/virtuanenvs/django-test-env/lib/python2.7/site-packages',
'/Users/khan/virtuanenvs/django-test-env/lib/python2.7/site-
packages/setuptools-0.6c11-py2.7.egg-info']
Server time: Mon, 22 Apr 2013 04:55:05 -0400
}}}

What did I miss? Please help! Thanks a bunch.

--
Ticket URL: <https://code.djangoproject.com/ticket/16626#comment:2>

Django

unread,
Jun 6, 2013, 2:48:58 AM6/6/13
to django-...@googlegroups.com
#16626: login_required attribute in class-based Generic Views
-------------------------------------+-------------------------------------
Reporter: szczav | Owner: nobody

Type: New feature | Status: closed
Component: Generic views | Version: master
Severity: Normal | Resolution:
Keywords: login_required | worksforme
decorator view generic views | Triage Stage:
Has patch: 1 | Unreviewed

Needs tests: 0 | Needs documentation: 0
Easy pickings: 0 | Patch needs improvement: 0
| UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by jarus):

With the `@classmethod` decorader the code example works fine.

{{{
from django.contrib.auth.decorators import login_required

class LoginRequiredMixin(object):

@classmethod


def as_view(cls):
return login_required(super(LoginRequiredMixin, cls).as_view())
}}}

I aggree with aaugustin that a mixin is the better solution instead a
attribute in the generic view but maybe it is possible to put this mixin
in `django.contrib.auth`.

--
Ticket URL: <https://code.djangoproject.com/ticket/16626#comment:3>

Django

unread,
Oct 30, 2016, 4:13:24 PM10/30/16
to django-...@googlegroups.com
#16626: login_required attribute in class-based Generic Views
-------------------------------------+-------------------------------------
Reporter: szczav | Owner: nobody

Type: New feature | Status: closed
Component: Generic views | Version: master
Severity: Normal | Resolution:
| worksforme
Keywords: login_required | Triage Stage:
decorator view generic views | Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by StephenChan):

For anyone else stumbling upon this ticket years later, three mixins
including `LoginRequiredMixin` were added by #24914 and made available in
Django 1.9. Docs
[https://docs.djangoproject.com/en/dev/topics/auth/default/#the-
loginrequired-mixin here].

--
Ticket URL: <https://code.djangoproject.com/ticket/16626#comment:4>

Reply all
Reply to author
Forward
0 new messages