Adding more validation to django admin user add forms - django

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.

Related

I am trying to create custom user registration form

I am getting this error.Below mentioned code is for forms.py
forms.py
from django import forms
from dappx.models import UserProfileInfo
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ['username','password','email']
class UserProfileInfoForm(forms.ModelForm):
class Meta:
model = UserProfileInfo
fields = ['portfolio_site','profile_pic']
from django.contrib.auth.forms import UserCreationForm
class UserRegisterForm(UserCreationForm):
"""
Form class to register a new user
"""
def __init__(self, *args, **kwargs):
super(UserRegisterForm, self).__init__(*args, **kwargs)
class Meta:
model = User
fields = ['username','password','email']
I found this tutorial a good reading source

Authentication for class based views in Django

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, )
...

how to make email field required in the django user admin

I want to make the email field required in the user admin add and
change pages. I read this post: Django User model email field: how to make it mandatory and I did this:
class MyUserCreationForm(UserCreationForm):
def __init__(self, *args, **kwargs):
super(MyUserCreationForm, self).__init__(*args, **kwargs)
# make user email field required
self.fields['email'].required = True
class UserAdmin(BaseUserAdmin):
form = MyUserCreationForm
add_form = MyUserCreationForm
add_fieldsets = ((None, {'fields': ('username', 'email',
'password1', 'password2'), 'classes': ('wide',)}),)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
This works fine in add user, but in change user I get the user's
encrypted password shown in the password field, instead of what you
normally see:
algorithm: pbkdf2_sha256 iterations: 24000 salt: ****** hash:
**************************************
Raw passwords are not stored, so there is no way to see this user's
password, but you can change the password using this form.
And when I try to save from the change screen it says "Please correct
the errors below." even though there are no errors shown.
How can I fix these issues in the change form?
Have a look at the source code of the UserAdmin.
The UserAdmin uses a UserChangeForm as it's formproperty and a UserCreationForm as it's add_form property. But you have overridden both of them with a class derived from UserCreationForm which is okay for the create view but doesn't work for the update view .
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import User
class EmailRequiredMixin(object):
def __init__(self, *args, **kwargs):
super(EmailRequiredMixin, self).__init__(*args, **kwargs)
# make user email field required
self.fields['email'].required = True
class MyUserCreationForm(EmailRequiredMixin, UserCreationForm):
pass
class MyUserChangeForm(EmailRequiredMixin, UserChangeForm):
pass
class EmailRequiredUserAdmin(UserAdmin):
form = MyUserChangeForm
add_form = MyUserCreationForm
add_fieldsets = ((None, {
'fields': ('username', 'email', 'password1', 'password2'),
'classes': ('wide',)
}),)
admin.site.unregister(User)
admin.site.register(User, EmailRequiredUserAdmin)
This should do the trick.

Manually register user with FormWizard and django-registration

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!

Extending user admin form in django

I'm trying to change user admin in Django. In my project the email address, first name and last name is required. I changed my user admin as following :
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
class UserAdmin(admin.ModelAdmin):
form = UserForm
list_display = ('first_name','last_name','email','is_active')
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
The problem is whenever I save a user with a password, it's displayed as without hashing. I guess the problem is, I need to hash the password field with my new form. But the old form does it, so is there a way that I can extend the oldform ?
You can subclass the existing UserChangeForm in django.contrib.auth.forms, and customise its behaviour, rather than subclassing forms.ModelForm.
from django.contrib.auth.forms import UserChangeForm
class MyUserChangeForm(UserChangeForm):
def __init__(self, *args, **kwargs):
super(MyUserChangeForm, self).__init__(*args, **kwargs)
self.fields['email'].required = True
self.fields['first_name'].required = True
self.fields['last_name'].required = True
class UserAdmin(admin.ModelAdmin):
form = MyUserChangeForm
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
The above will use the default behaviour for the user password, which is to display the password hash, and link to the password change form. If you want to modify that, I would look at SetPasswordForm, to see how the password is set in the Django admin.