How to require login for Django Generic Views?
I want to restrict access to URLs handled by Django Generic Views.
For my Views I know that login_required
decorator does the job.
Also Create/Delete/Update Generic Views take the login_required
argument, but I couldn't find a way to do this for other Generic Views.
Solution 1:
Django >= 1.9 or using django-braces
Django 1.9 has introduced a LoginRequiredMixin
that is used thus:
from django.contrib.auth.mixins import LoginRequiredMixin
class MyView(LoginRequiredMixin, View):
login_url = '/login/'
redirect_field_name = 'redirect_to'
If you are using an older version of django you can use pretty much the same mixin from django-braces - the Django version was based on the django-braces version. django-braces 1.4.x still supports Django 1.4 so you can use it with pretty old versions.
Older Methods
I found this question while googling for how to decorate class based views, so to add the answer for that:
This is covered in the documentation section on decorating class based views. There is the urls.py
wrapper, or you can apply the decorator to the dispatch()
method. Examples from the documentation:
Decorating in URL conf
from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView
from .views import VoteView
urlpatterns = patterns('',
(r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
)
Decorating the class
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView
class ProtectedView(TemplateView):
template_name = 'secret.html'
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(ProtectedView, self).dispatch(*args, **kwargs)
See the documentation linked to above for more details.
Solution 2:
For Django < 1.5, you can add a decorator by wrapping the function in your urls, which allows you to wrap the generic views:
from django.contrib.auth.decorators import login_required
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
(r'^foo/$', login_required(direct_to_template), {'template': 'foo_index.html'}),
)
The function-based generic views are deprecated in Django 1.4 and were removed in Django 1.5. But the same principle applies, just wrap the view function of the class based view with the login_required
decorator:
login_required(TemplateView.as_view(template_name='foo_index.html'))
Solution 3:
The generic views have changed from functions to objects with version 1.3 of Django. As such, there is a slight change needed for Will McCutchen and Will Hardy answers to work with version 1.3:
from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView
urlpatterns = patterns('',
(r'^foo/$', login_required(TemplateView.as_view(template_name='foo_index.html'))),
)
Also the documentation describes how to do this as well.
Solution 4:
If you don't want to write your own thin wrapper around the generic views in question (as Aamir suggested), you can also do something like this in your urls.py
file:
from django.conf.urls.defaults import *
# Directly import whatever generic views you're using and the login_required
# decorator
from django.views.generic.simple import direct_to_template
from django.contrib.auth.decorators import login_required
# In your urlpatterns, wrap the generic view with the decorator
urlpatterns = patterns('',
(r'', login_required(direct_to_template), {'template': 'index.html'}),
# etc
)
Solution 5:
For django 1.11, You can use LoginRequiredMixin for Class-based Views
in settings file you should add
LOGIN_URL="/login/"
in your views.py
from django.contrib.auth.mixins import LoginRequiredMixin
class RestaurantLocationCreateView(LoginRequiredMixin,CreateView):
....