107π
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'))
111π
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.
- [Django]-How do I package a python application to make it pip-installable?
- [Django]-How to access array elements in a Django template?
- [Django]-Django Forms: if not valid, show form with error message
39π
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.
- [Django]-Django annotation with nested filter
- [Django]-How to produce a 303 Http Response in Django?
- [Django]-Django-Bower + Foundation 5 + SASS, How to configure?
12π
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
)
- [Django]-How does the get_or_create function in Django return two values?
- [Django]-Manager isn't accessible via model instances
- [Django]-What is the SQL ''LIKE" equivalent on Django ORM queries?
8π
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):
....
- [Django]-How to check if ManyToMany field is not empty?
- [Django]-How can I get MINIO access and secret key?
- [Django]-How to get the current language in Django?
8π
Another way to achieve this is below, I like that it is quite similar to how itβs done with function-based views and does not require modifying urls.py
or overriding dispatch
:
@method_decorator(login_required, name='dispatch')
class YourGenericViewSubclass(TemplateView):
#
# View methods
#
- [Django]-Django rest framework change primary key to use a unqiue field
- [Django]-Profiling Django
- [Django]-How to access a dictionary element in a Django template?
5π
In Django =>3.0 it gets pretty easy:
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView
@method_decorator(login_required(login_url='/login/'), name='dispatch')
class ProtectedView(TemplateView):
template_name = 'secret.html'
for reference: https://docs.djangoproject.com/en/3.0/topics/class-based-views/intro/#decorating-the-class
- [Django]-CSRF Failed: CSRF token missing or incorrect
- [Django]-IOS app with Django
- [Django]-Django project models.py versus app models.py
3π
I wanted a re-usable way to require auth on many views derived from generic views. I created a replacement dispatch function which I can add to my view class in the same way as itβs other declarations.
class Index(generic.ListView):
model = models.HomePage
dispatch = auth.dispatch
auth.dispatch is where we do the work:
def dispatch(self, request, *args, **kw):
"""Mix-in for generic views"""
if userSession(request):
return super(self.__class__, self).dispatch(request, *args, **kw)
# auth failed, return login screen
response = user(request)
response.set_cookie('afterauth', value=request.path_info)
return response
- [Django]-Django composite unique on multiple model fields
- [Django]-Django β how to unit test a post request using request.FILES
- [Django]-Effects of changing Django's SECRET_KEY
1π
Use the following:
from django.contrib.auth.decorators import login_required
@login_required
def your_view():
# your code here
- [Django]-Django migration strategy for renaming a model and relationship fields
- [Django]-Visual Editor for Django Templates?
- [Django]-Default filter in Django model
1π
The following could solve this issue.
// in views.py:
class LoginAuthenAJAX(View):
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated:
jsonr = json.dumps({'authenticated': True})
else:
jsonr = json.dumps({'authenticated': False})
return HttpResponse(jsonr, content_type='application/json')
// in urls.py
path('login_auth', views.LoginAuthenAJAX.as_view(), name="user_verify"),
//in xxx.html
<script src = β{% static βxxx/script.jsβ %}β
var login_auth_link = β{% url βuser_verifyβ %}β
</script>
// in script.js
$.get(login_auth_link, {
'csrfmiddlewaretoken' : csrf_token,
},
function(ret){
if (ret.authenticated == false) {
window.location.pathname="/accounts/login/"
}
$("#message").html(ret.result);
}
)
- [Django]-Is there a naming convention for Django apps
- [Django]-Django template display item value or empty string
- [Django]-How to rename items in values() in Django?
0π
I had been struggling with finding the answer to this for a long time till I found this workaround.
In models.py do:
from django.db import models
class YourLoginModel:
fullname = models.CharField(max_length=255, default='your_name', unique=True)
email = models.EmailField(max_length=255, unique=True)
username = models.CharField(max_length=255, unique=True)
password = models.CharField(max_length=255) #using werkzeug's
#generate_password_hash on plaintext password before committing to database model
In forms.py do:
from django import forms
from .models import YourLoginModel
class LoginForm(forms.ModelForm):
class Meta:
model = YourLoginModel
fields = ('username', 'password')
In views.py login logic:
def login(request):
#login logic here
# init empty form
form = LoginForm()
if request.method == 'POST':
try:
# peforms a Select query in db and gets user with log in username
user_logging_in = User.objects.get(username=request.POST['username'])
# assign user hash to var
hash = user_logging_in.password
# assign form str passs word to var
password = request.POST['password']
# if the user does not exist
except ObjectDoesNotExist:
html_response = 'User does not exists'
return HttpResponse(html_response)
# peform password and hash check
if check_password_hash(hash, password):
#using sessions cookies to know who we're interacting with
request.session['username'] = request.POST['username']
#set expiry date of the session
request.session.set_expiry(0) # 0 means when the browser is closed
return redirect('yourapp:home')
else:
return HttpResponse('password was incorrect')
html = 'Login'
return render(request, 'login.html', {'form': form})
In app view you want to perform login_required on do
from django.views.generic import TemplateView
class yourTemplateView(TemplateView):
template_name = 'your_template.html'
def dispatch(self, request, *args, **kwrags):
if not request.session.has_key('username'):
#return HttpResponse('not logged in')
return redirect('yourapp:login.html')
else:
return render(request, 'your_view.html')
- [Django]-Creating email templates with Django
- [Django]-Django template can't see CSS files
- [Django]-Django template how to look up a dictionary value with a variable