class AdminView(generic.ListView):
model = get_user_model()
fields = ['first_name', 'username', 'is_active']
template_name = 'users/admin.html'
class AdminUpdateView(UpdateView):
model = get_user_model()
fields = ['is_active']
template_name = 'users/user_update.html'
success_url = reverse_lazy('users:admin')
There are two views in django which I have created and I want them to be accessed only when the admin/staff logins. How do I go about it?
You can use the UserPassesTestMixin [Django-doc] and LoginRequiredMixin [Django-doc] mixins, and specify as condition that the user should be an is_superuser. Since you need these twice, we can make first a composite mixin:
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
class AdminStaffRequiredMixin(LoginRequiredMixin, UserPassesTestMixin):
def test_func(self):
return self.request.user.is_superuser or self.request.user.is_staff
Next you can add the mixin to your class-based views:
class AdminView(AdminStaffRequiredMixin, generic.ListView):
model = get_user_model()
fields = ['first_name', 'username', 'is_active']
template_name = 'users/admin.html'
class AdminUpdateView(AdminStaffRequiredMixin, UpdateView):
model = get_user_model()
fields = ['is_active']
template_name = 'users/user_update.html'
success_url = reverse_lazy('users:admin')
You can use UserPassesTestMixin:
from django.contrib.auth.mixins import UserPassesTestMixin
class AdminView(UserPassesTestMixin, generic.ListView):
model = get_user_model()
fields = ['first_name', 'username', 'is_active']
template_name = 'users/admin.html'
def test_func(self):
return self.request.user.is_staff or self.request.user.is_superuser
Use decorators, with #login_required you can tell this views will be only accesseed when user os logged in, you can pass parameters to it too or create one your own to validate if the logged user on the request can see or no your view
With Login Required
from django.contrib.auth.decorators import login_required
#login_required(login_url='/accounts/login/')
class AdminView(generic.ListView):
...
#login_required(login_url='/accounts/login/')
class AdminUpdateView(UpdateView):
...
https://docs.djangoproject.com/en/2.0/topics/auth/default/#the-login-required-decorator
With Permission
from django.contrib.auth.decorators import permission_required
#permission_required('user.is_staff')
def my_view(request):
...
https://docs.djangoproject.com/en/2.0/topics/auth/default/#the-permission-required-decorator
If you want to use the LoginRequiredMixin, you still can. And it is much simpler. Just extend the LoginRequiredMixin in all you classes so that they are like this.
class AdminView(LoginRequiredMixin, generic.ListView):
model = get_user_model()
fields = ['first_name', 'username', 'is_active']
template_name = 'users/admin.html'
class AdminUpdateView(LoginRequiredMixin, UpdateView):
model = get_user_model()
fields = ['is_active']
template_name = 'users/user_update.html'
success_url = reverse_lazy('users:admin')
This ensures that the user is already logged in before allowing any operations. Then, check if the user is an admin by adding the following code to each of the classes;
def dispatch(self, request, *args, **kwargs):
if not self.request.user.is_staff:
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
Your code should now look like this:
class AdminView(LoginRequiredMixin, generic.ListView):
model = get_user_model()
fields = ['first_name', 'username', 'is_active']
template_name = 'users/admin.html'
def dispatch(self, request, *args, **kwargs):
if not self.request.user.is_staff:
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
class AdminUpdateView(LoginRequiredMixin, UpdateView):
model = get_user_model()
fields = ['is_active']
template_name = 'users/user_update.html'
success_url = reverse_lazy('users:admin')
def dispatch(self, request, *args, **kwargs):
if not self.request.user.is_staff:
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
You can use IsAdminUser permission by rest framework
from rest_framework import permissions
class AdminView(generic.ListView):
permission_classes = (permissions.IsAdminUser, )
...
Related
I am getting type error while setting current user to created_by field in my model
forms.py
class MyModelForm(forms.ModelForm):
class Meta:
model = Model
fields = ('name',)
def __init__(self, *args, creator, **kwargs):
super().__init__(*args, **kwargs)
self.creator = creator
def save(self, *args, **kwargs):
self.instance.created_by = self.creator
return super().save(*args, **kwargs)
views.py
class CreatEEView(LoginRequiredMixin, CreateView,):
form_class = ''
template_name = ''
success_url = ''
Models.py
class MYmodel(models.Model):
name = models.CharField()
created_by = models.ForeignKey()
You do not need to use a custom form for that because CreateView is creating ModelForm for you, what you can do is like that:
from django.db import models
class MYmodel(models.Model):
name = models.CharField()
created_by = models.ForeignKey()
Then you can override the form_valid method. This method is called when valid form data has been POSTed.
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from myapp.models import MYmodel
class CreatEEView(LoginRequiredMixin, CreateView):
model = MYmodel
fields = ['name']
def form_valid(self, form):
form.instance.created_by = self.request.user
return super().form_valid(form)
You can find the same example in Django documents in this Link
I am working on some projects and trying to the list view of the book. I used Django Rest-Framework-Simplejwt to generate tokens and mod header for authentication. When I tried to request a token for a user such as the admin user, and enter it into the mod header, the request is still unauthorized. I tried to do it a couple of times, but still not working.
Views.py
from rest_framework import generics, permissions
from rest_framework.permissions import IsAuthenticated
from rest_framework.exceptions import ValidationError
from django.contrib.auth.models import User
from .models import Book
from .serializers import (
BookSerializer,
RegistrationSerializer
)
class BookCreateView(generics.CreateAPIView):
"""Create a Book"""
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = (IsAuthenticated,)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
class BookListView(generics.ListAPIView):
"""Show all books"""
serializer_class = BookSerializer
permission_classes = (IsAuthenticated,)
def get_queryset(self):
user = self.request.user
return Book.objects.filter(user=user)
class BookDetailView(generics.RetrieveAPIView):
"""Show detail of the book"""
serializer_class = BookSerializer
permission_classes = (IsAuthenticated,)
def get_queryset(self):
user = self.request.user
return Book.objects.filter(user=user)
class BookUpdateView(generics.RetrieveUpdateDestroyAPIView):
"""update detail of the book"""
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = (IsAuthenticated,)
def delete(self, request, *args, **kwargs):
book = Book.objects.filter(user=self.request.user, pk=kwargs['pk'])
if book.exists():
return self.destroy(request, *args, **kwargs)
else:
raise ValidationError('Book is not yours!')
def perform_update(self, serializer, **kwargs):
book = Book.objects.get(pk=self.kwargs['pk'])
if self.request.user != book.user:
raise ValidationError("You are not the owner of this book")
serializer.save(user=self.request.user, book=book)
class UserRegistrationView(generics.CreateAPIView):
queryset = User.objects.all()
serializer_class = RegistrationSerializer
permission_classes = [permissions.AllowAny]
Serializers.py
from rest_framework import serializers
from django.contrib.auth.models import User
from .models import Book
class BookSerializer(serializers.ModelSerializer):
"""Serializer for Book"""
class Meta:
model = Book
fields = (
'id','user',
'title', 'author',
'description', 'image')
read_only_fields = ('id', 'user')
class RegistrationSerializer(serializers.ModelSerializer):
password = serializers.CharField(style={'input type':'password'}, write_only=True)
class Meta:
model = User
fields = ('username', 'email', 'password')
def create(self, validated_data):
user = User.objects.create(
username=validated_data['username'],
email=validated_data['email'])
user.set_password(validated_data['password'])
user.save()
return user
I entered the correct Token (copy&paste), but still not able to authenticate.
You are using "Token <eyJ..>". But instead your token should be like "Bearer <eyJ..>"
Some of Simple JWT’s behavior can be customized through settings variables in settings.py
class MyModel(models.Model):
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
if getattr(self, 'my_attr', False):
# do things
class MyForm(forms.ModelForm):
def clean(self)
cleaned_data = super().clean()
if self.has_changed():
self.instance.my_attr = self.get_the_needed_info()
return cleaned_data
class Meta:
model = MyModel
fields ='__all__'
#admin.register(MyModel)
class MyAdmin(admin.ModelAdmin)
form = MyForm
During MyModel.save(), I need to check for a condition that is evaluated in ModelForm.clean().
During clean(), I assign the attribute my_attr to self.instance.
It is working
it seems to be
thread-safe
(within an atomic transaction).
Is there any reason I miss, that urges a refactoring?
According to django docs, using the ModelForm to set an existing instance attribute, is recommended.
views.py:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from myapp.models import Author
class AuthorCreate(LoginRequiredMixin, CreateView):
model = Author
fields = ['name']
def form_valid(self, form):
form.instance.created_by = self.request.user
return super().form_valid(form)
I have a UserModel and a UserProfile Model and I would like to use FormWizard from the formtools to both register the user and setup a userprofile with necessary inputs from the user.
I am struggling with some concepts and trying to patch this together with no success so far.
I get the error message:
AttributeError at /accounts/register/
'MyRegistrationView' object has no attribute 'request'
forms.py
class UserForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput())
password2 = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2', 'first_name', 'last_name')
class UserProfileForm(forms.ModelForm):
course_accid = CourseModelChoiceField(Course.objects.all(), empty_label=None)
class Meta:
model = UserProfile
fields = ('picture','reg_completed')
url.py
urlpatterns = solid_i18n_patterns ('',
url(r'^accounts/register/$', RegistrationWizard.as_view([UserForm, UserProfileForm]), name='registration_register'),
url(r'^accounts/', include('registration.backends.simple.urls')),
views.py
from formtools.wizard.views import SessionWizardView
from registration.signals import *
from django.core.files.storage import FileSystemStorage
from django.conf import settings
class MyRegistrationView(RegistrationView):
def get_success_url(self, user):
return '/index/'
TEMPLATES = {"0": "registration/registration_form_wiz.html",
"1": "registration/registration_form_wiz.html",
}
class RegistrationWizard(SessionWizardView):
form_list = [UserForm, UserProfileForm]
file_storage = FileSystemStorage(location=settings.MEDIA_ROOT + '/photos')
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
def done(self, form_list, **kwargs):
userreg = MyRegistrationView()
for form in form_list:
if isinstance(form, UserForm):
userreg.register(form)
elif isinstance(form, UserProfileForm):
userprofile = form.save(commit=False)
user = self.request.user
userprofile.user = user
userprofile.save()
return HttpResponseRedirect('/index/')
Any help for what is wrong or if another approach would be better, is very welcome.
Thanks!
If we need to add more validation in django admin user add form like making the first name and last name and email compulsory.. Whats the way of achieving this??
You must create your own user form and adding your required fields:
class UserForm(forms.ModelForm):
class Meta:
model = User
def __init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
self.fields['email'].required = True
self.fields['first_name'].required = True
self.fields['last_name'].required = True
Then override the form in your ModelAdmin:
class UserAdmin(admin.ModelAdmin):
form = UserForm
And then unregister the normal admin User before registering your own:
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
This extends Geoffroy's answer:
from django.contrib.auth.forms import UserCreationForm
class UserForm(UserCreationForm):
class Meta:
model = User
def __init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
self.fields['email'].required = True
self.fields['first_name'].required = True
self.fields['last_name'].required = True
ModelAdmin:
from django.contrib.auth.admin import UserAdmin
class CustomUserAdmin(UserAdmin):
add_form = UserForm
add_fieldsets = (
(None, {'fields':('username','password1','password2','first_name','last_name','email'),}),)
And then unregister as above:
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
Just write your own form class and tell the ModelAdmin, to use that as the form.