I am working on blog project in which I added an add post which add post now I want only the superuser can add post and that page is visible only to superuser.
1st Method
Views.py
class AddPostView(CreateView):
model = Post
template_name = 'MainSite/add_post.html'
fields = '__all__'
this is my current view I am able to achieve authenticate for superuser using 2nd method
2nd Method
class AddPostView(View):
def get(self,request):
if request.user.is_superuser == True:
return render(...)
else:
pass
How can I achieve the same result using 1st method.I tried using LoginRequiredMixin but nothing is happening . I just import LoginRequiredMixin and use it like this .
class Addpost(CreateView,LoginRequiredMixin):
...
Thanks in advance and advice will be helpful.
You can work with a UserPassesTestMixin mixin [Django-doc]:
from django.contrib.auth.mixins import UserPassesTestMixin
class AddPostView(UserPassesTestMixin, CreateView):
# …
def test_func(self):
return self.request.user.is_superuser
# …
You can encapsulate this in a mixin:
from django.contrib.auth.mixins import UserPassesTestMixin
class AdminRequiredMixin(UserPassesTestMixin):
def test_func(self):
return self.request.user.is_superuser
and then use this mixin:
class AddPostView(AdminRequiredMixin, CreateView):
# …
def test_func(self):
return self.request.user.is_superuser
# …
Mixins should be put before the actual view in the inheritance hierarchy: otherwise these appear after the view in the method resolution order (MRO), and thus likely will not override the behavior (correctly).
class AddPostView(CreateView,LoginRequiredMixin):
model = Post
template_name = 'MainSite/add_post.html'
fields = '__all__'
def dispatch(self, request, *args, **kwargs):
if request.user.is_anonymous:
return redirect_to_login(self.request.get_full_path(), self.get_login_url(), self.get_redirect_field_name())
elif request.user.is_superuser:
return render(.....)
else
return super(AddPostView, self).dispatch(request, *args, **kwargs)
Use method_decorator and user_passes_test to achieve this
from django.views.generic import View
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import user_passes_test
class AddPostView(View):
#method_decorator(user_passes_test(lambda u: u.is_superuser))
def post(self, *args, **kwargs):
pass
Related
My site has users and entries. I want to create a Django decorator to restring users to delete or update others entries.
But I have been able to do some.
I was thinking something like this
class EntryUpdate(generic.UpdateView):
model = Entry
fields = ['...']
....
#user_passes_test(lambda user: current.user.id == entry.user.id)
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(EntryUpdate, self).dispatch(*args, **kwargs)
If you already using Class Based views, use UserPassesTestMixin instead of decorator
from django.contrib.auth.mixins import UserPassesTestMixin
class EntryUpdate(UserPassesTestMixin, generic.UpdateView):
model = Entry
fields = ['...']
def test_func(self):
return self.request.user == self.get_object().user
I have this code:
#decorators.py
from django.contrib.auth.decorators import user_passes_test
def superuser_required(func):
return user_passes_test(
lambda u: u.is_authenticated() and u.is_superuser)(func)
# views.py
#superuser_required
def dashboard_candidates(request):
persons = Person.objects.all()
return render(request, 'my_template.html', {'persons': persons})
How to transform this function in ListView adapting the decorator?
I try:
PersonList(LoginRequiredMixin, ListView)
model = Person
paginate_by = 10
I do not know how to implement the decorator mentioned above.
Engraçado, só funcionou desse jeito.
from django.utils.decorators import method_decorator
class SuperuserRequiredMixin(object):
#method_decorator(user_passes_test(lambda u: u.is_authenticated() and u.is_superuser))
def dispatch(self, *args, **kwargs):
return super(SuperuserRequiredMixin, self).dispatch(*args, **kwargs)
class PersonList(SuperuserRequiredMixin, ListView):
model = Person
paginate_by = 20
I feel like this is really simple and I'm just missing it.
I have a very simple generic class based view detail.
When I do teh get_object I want to make sure that the request.user is in the set that belongs to the object. If not, redirect them to the login.
Here's my view:
class AwesomeDetail(LoginRequiredMixin, DetailView):
"""
An awesome detail
"""
template_name = "awesomeness/detail.html"
def get_object(self):
awesomeness = ModelName.objects.get(id=self.kwargs['pk'])
if self.request.user in awesomeness.staff.all():
return awesomness
else:
return redirect('account_login')
Staff is a many to many to users. What am I missing? The redirect isn't happening. It renders the template, but of course, awesomeness is missing.
UserPassesTestMixin was introduced in Django 1.9.
You define a test_func method to return True/Fales depending on whether the test passes.
If the user fails the test they will be redirected to settings.LOGIN_URL with a redirect field.
UserPassesTestMixin supports any of the fields for AccessMixin.
from django.contrib.auth.mixins import UserPassesTestMixin
class AwesomeDetail(UserPassesTestMixin, LoginRequiredMixin, DetailView):
"""
An awesome detail
"""
template_name = "awesomeness/detail.html"
model = ModelName
def test_func(self):
if self.request.user in self.object.staff.all():
return True
else:
return False
I'm not very sure about this, but sounds like get method is the one you should work on:
class AwesomeDetail(LoginRequiredMixin, DetailView):
"""
An awesome detail
"""
template_name = "awesomeness/detail.html"
def get(self, request, *args, **kwargs):
self.object = self.get_object()
if not self.request.user in self.object.staff.all():
return redirect('account_login')
else:
return super(AwesomeDetail, self).get(request, *args, **kwargs)
I inherited a Django(1.5.1) project and I need to put one view behind a #login_required decorator. Here is what i have in views.py:
I got this snippet of code from here and it looks like its purpose is to allow someone to apply the #login_requireddecorator to a class
class LoginRequiredMixin(object):
"""
View mixin which verifies that the user has authenticated.
NOTE:
This should be the left-most mixin of a view.
"""
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(*args, **kwargs)
class PermissionRequiredMixin(object):
login_url = settings.LOGIN_URL
permission_required = None
raise_exception = False
redirect_field_name = '/workers/'
def dispatch(self, request, *args, **kwargs):
# Verify class settings
if self.permission_required == None or len(
self.permission_required.split(".")) != 2:
raise Error("'PermissionRequiredMixin' requires "
"'permission_required' attribute to be set.")
has_permission = request.user.has_perm(self.permission_required)
if not has_permission:
if self.raise_exception:
return HttpResponseForbidden()
else:
path = urlquote(request.get_full_path())
tup = self.login_url, self.redirect_field_name, path
return HttpResponseRedirect("%s?%s=%s" % tup)
return super(PermissionRequiredMixin, self).dispatch(
request, *args, **kwargs)
I then apply this to the view i want to add permissions to like so:
class RootWorkerView(LoginRequiredMixin, PermissionRequiredMixin, APIView):
renderer_classes = (WorkersJSONRenderer, JSONRenderer,
BrowsableAPIRenderer)
def get(self, request):
worker_list = rest_models.WorkerList(request)
serializer = WorkerListSerializer(worker_list)
return Response(serializer.data)
The APIView argument is a carry over, as before it was the only argument. Is this correct?
When run, I get nothing. The template for the view I want to secure shows up with no login prompt.
Relevant snippet from urls.py:
url(r'^workers/$', views.RootWorkerView.as_view(),
name='root_worker_view'),
url(r'^login/$', 'django.contrib.auth.views.login',
{'template_name': 'dashboard/login.html'}),
/login/ does work, and I can login successful, so that's not the issue.
I feel like #method_decorator(login_required) isnt doing its job. Any ideas?
You can add the decorator in the urls.py
from django.contrib.auth.decorators import login_required
url(r'^workers/$', login_required(views.RootWorkerView.as_view()))
This worked for me.
now you can use Django builtin LoginRequiredMixin
from django.contrib.auth.mixins import LoginRequiredMixin
class MyView(LoginRequiredMixin, View):
login_url = '/login/'
redirect_field_name = 'redirect_to'
https://docs.djangoproject.com/en/3.2/topics/auth/default/#the-loginrequired-mixin
I have the file userprofiles/mixins.py in which I've created this mixin
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
class LoginRequiredMixin(object):
#method_decorator(login_required(login_url = '/login/'))
def dispatch(self, request, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
In my file userprofiles/views.py I have the following class based view named ProfileView of this way:
from .mixins import LoginRequiredMixin
class ProfileView(LoginRequiredMixin,TemplateView):
template_name = 'profile.html'
def get_context_data(self, **kwargs):
context = super(ProfileView, self).get_context_data(**kwargs)
if self.request.user.is_authenticated():
context.update({'userprofile': self.get_userprofile()})
return context
def get_userprofile(self):
return self.request.user.userprofile
In this class based view named ProfileView I could inherit from LoginRequiredMixin without any trouble
These mixin LoginRequiredMixin I also applied to the class based view named AlbumListView which is located in other module or app artists/views.py.
The class based view AlbumListView is this:
from sfotipy.userprofiles.mixins import LoginRequiredMixin
class AlbumListView(LoginRequiredMixin,ListView):
model = Album
template_name = 'album_list.html'
def get_queryset(self):
if self.kwargs.get('artist'):
queryset = self.model.objects.filter(artist__slug__contains=self.kwargs['artist'])
else:
queryset = super(AlbumListView, self).get_queryset()
return queryset
The unique way for my IDE don't mark error when I import the LoginRequiredMixin for I inherit from it is of this way:
from sfotipy.userprofiles.mixins import LoginRequiredMixin
I know that this import way is not correct, because is a absolute import and the right way is doing a relative import.
Other way in where should work is this:
from userprofiles.mixins import LoginRequiredMixin
But, when I want test I get the following error message...
How to can I do this import and that works?
Thanks for the orientation :D