I've been developing a school application for allowing the principal and his teachers to analyze data. The principal needs to add his own people to the system. I think using Django's admin panel would be a really good choice for that.
Here, I am the superuser and the principal is the staff (who can manage things on the admin panel).
As a superuser, I can see the following output:
And here is the view for the staff:
I also have two groups (school one, school two) in the system:
The principal (staff user) John Doe belongs to the group "School Two" which has the permissions of add/change/delete/view users.
My question is how can I list the users for a staff to see only his group of people? (no superuser and no other groups' people).
Let me share some source code I implemented to for this custom user admin view:
The forms.py file:
class UserAdminCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
User = get_user_model()
model = User
fields = ('email',)
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
user.is_staff = True
if commit:
user.save()
return user
class UserAdminChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
class Meta:
User = get_user_model()
model = User
fields = '__all__' #fields = ('email', 'password', 'is_active','is_staff', 'groups')
def __init__(self, *args, **kwargs):
super(UserAdminChangeForm, self).__init__(*args, **kwargs)
f = self.fields.get('user_permissions', None)
if f is not None:
f.queryset = f.queryset.select_related('content_type')
def clean_password(self):
return self.initial["password"]
Here is the admin.py file
from django.contrib import admin
from .models import User
from .forms import UserAdminCreationForm, UserAdminChangeForm
class MyUserAdmin(admin.ModelAdmin):
form = UserAdminChangeForm
add_form = UserAdminCreationForm
list_display = ('email', 'first_name', 'last_name', 'is_staff', 'is_active', 'is_email_verified')
list_filter = ('is_staff', 'is_active', 'groups')
readonly_fields = ('last_login', 'date_joined',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('first_name','last_name')}),
('Permissions', {'fields': ('is_active','is_staff', 'groups')}),
('Important dates', {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('first_name','last_name','email', 'password1', 'password2')}
),
)
search_fields = ('first_name', 'last_name', 'email',)
ordering = ('email',)
filter_horizontal = ()
admin.site.register(User, MyUserAdmin)
I am using Django 2.1. Again, how can I display users who belong to a certain group? For example, here in this case, when John Doe (staff) logged in as admin, he should only see himself (and in future other groups members) because he only belongs to "School Two".
I would be glad if I can get some help with this.
You can override the get_queryset method for the admin class like this;
class MyUserAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
# Filter here by user group
return qs.filter(groups__id__in=request.user.groups.all())
Docs for this are here; https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_queryset
Related
How can i add extended Profile model fields (fields which are not available in custom user model fields) into custom users admin users.admin?
what i am trying to do is that i want too see Profile model fields like photo, date_of_birth, country, phone etc.. inside the Personal Info(see in image) & i can make changes in it from here.
profile model
from django.db import models
from django.dispatch import receiver
from django.urls import reverse
from django.db.models.signals import post_save
from django.contrib.auth import get_user_model # or from users.models import User
User = get_user_model()
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
photo = models.ImageField(null=True, blank=True)
date_of_birth = models.DateField(null=True, blank=True)
phone = models.IntegerField(null=True, blank=True)
country = models.CharField(max_length=150, null=True, blank=True)
city = models.CharField(max_length=150, null=True, blank=True)
bio = models.TextField(max_length=150, null=True, blank=True)
def __str__(self):
return str(self.user.email)
def get_absolute_url(self):
return reverse('profiles:profile-detail', kwargs={'pk':self.pk})
def post_save_user_model_receiver(sender, instance, created, *args, **kwargs ):
# when a user is created(custom user model)like signup or through admin it will create those user's profile too
if created:
try:
Profile.objects.create(user=instance) # it create those user's profile
except:
pass
post_save.connect(post_save_user_model_receiver, sender=User)
users.admin
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth import get_user_model # or from .models import User
from .forms import UserAdminCreationForm, UserAdminChangeForm
# Register your models here.
User = get_user_model() # or from .models import User
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserAdminChangeForm
add_form = UserAdminCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'first_name', 'get_phone', 'last_login', 'date_joined', 'is_admin')
list_filter = ('admin', 'staff', 'active')
list_select_related = ('profile',)
def get_phone(self, instance): # to show the Phone in list display from the Profile Model
return instance.profile.phone
get_phone.short_description = 'Phone'
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal Info', {'fields': ('first_name', 'last_name',)}),
('Permissions', {'fields': ('admin', 'staff', 'active')}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'first_name', 'last_name', 'password1', 'password2', )
}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
# Remove Group Model from admin. We're not using it.
admin.site.unregister(Group)
form which is used to edit users in admin
from django import forms
from django.contrib.auth import get_user_model # or from .models import User
from django.contrib.auth.forms import ReadOnlyPasswordHashField
User = get_user_model() # this method will return the currently active user model
# or from .models import User
class UserAdminCreationForm(forms.ModelForm):
"""
A form for creating new users in admin panel. Includes all the required
fields, plus a repeated password.
"""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Password don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
return user
class UserAdminChangeForm(forms.ModelForm):
"""
A form for updating users in admin panel. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 'password', 'active', 'staff', 'admin')
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial['password']
I would recommend that you override the User model.
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, \
PermissionsMixin
class UserManger(BaseUserManager):
"""
Add extra calling functionalities here
"""
pass
class User(AbstractBaseUser, PermissionsMixin):
"""Custom user model"""
pass
objects = UserManger()
This is the basic format. Add the extra profile fields in the model
in setting.py add
AUTH_USER_MODEL = '{{ app_name }}.{{ model_name }}'
# eg. 'core.User'
I customed the User in Django following the code providing by the Documentation (for the models.py and the admin.py)
I have a custom User using his email to auth (and not the username)
I can create new user but I cannot delete them in the django admin panel. When I try i go this error message: FOREIGN KEY constraint failed
models.py
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class MyUserManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, date_of_birth, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(
email,
password=password,
date_of_birth=date_of_birth,
)
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth']
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
admin.py
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from register.models import MyUser
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = MyUser
fields = ('email', 'date_of_birth')
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = MyUser
fields = ('email', 'password', 'date_of_birth', 'is_active', 'is_admin')
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'date_of_birth', 'is_admin')
list_filter = ('is_admin',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('date_of_birth',)}),
('Permissions', {'fields': ('is_admin',)}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'date_of_birth', 'password1', 'password2')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
# Now register the new UserAdmin...
admin.site.register(MyUser, UserAdmin)
# ... and, since we're not using Django's built-in permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)
view.py
from django.contrib.auth import login, authenticate
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render, redirect
from django.contrib.auth import logout
from django.core.mail import send_mail
from .admin import UserCreationForm
def registration_view(request):
context = {}
if request.POST:
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
email = form.cleaned_data.get('email')
raw_password = form.cleaned_data.get('password1')
account = authenticate(email=email, password=raw_password)
login(request, account)
return render(request, 'register/home.html')
else:
context['registration_form'] = form
else:
form = UserCreationForm()
context['registration_form'] = form
return render(request, 'register/signup.html', context)
Mostly you get this error when the user you are trying to delete has some records associated in other tables.
Two options are:
Delete the associated records from the other tables first. And then try to delete this user.
Add on delete cascade option to the other tables' foreign keys referring to the user table. (This option will automatically remove any associated records from the other tables for the user you are trying to delete.)
I would to add a User to a permission group automatically when create a User. I have hear about user.groups.add(group) and group.user_set.add(user). But it doesn't work. My final purpose is to have 3 kind of users:
SuperAdmin: One superadmin to manage the site.
Administrators: User administrators. Which can manage regular users. Upload photos, add new Users to manage, etc.
Regular Users: The normal users which will use the aplicación. They don't have any permission, just login the site, but not the adminSite.
MODELS.PY
from django.db import models
from django.contrib.auth.models import AbstractUser, Group
from django.db.models.signals import post_save
from django.dispatch import receiver
# Create your models here.
class MyUser(AbstractUser):
descripcion = models.TextField(blank=True)
telefono = models.PositiveSmallIntegerField(default=000)
avatar = models.ImageField(upload_to='users/avatar/', blank=True)
def __str__(self):
return self.username
class RegularUser(MyUser):
MyUser.is_staff = False
MyUser.is_superuser = False
class Meta:
verbose_name = 'Usuario Regular'
verbose_name_plural = 'Usuarios Regulares'
class AdminUser(MyUser):
usuarios = models.ManyToManyField(RegularUser, help_text="Selecciona los usuarios que administra")
MyUser.is_staff = True
class Meta:
verbose_name = 'Administrador'
verbose_name_plural = 'Adminsitradores'
ADMIN.PY
from django.contrib import admin
from django import forms
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.contrib.auth.models import Group
from myApp.models import MyUser, RegularUser, AdminUser
# Register your models here.
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required fields,
plus a repeated password"""
password1 = forms.CharField(label='Contraseña', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repita Contraseña',
widget=forms.PasswordInput)
class Meta:
model = MyUser
fields = ('email',
'first_name',
'last_name',
'telefono',
'avatar',
'groups',)
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Las contraseñas no coinciden")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on the user
, but replaces the password field with admin's password
hash display field"""
password = ReadOnlyPasswordHashField()
class Meta:
model = MyUser
fields = ('username',
'email',
'password',
'first_name',
'last_name',
'descripcion',
'telefono',
'avatar',
)
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
class AdminCreationForm(forms.ModelForm):
"""A form for creating new Admin users. Including all required fields,
plus a repeated password"""
password1 = forms.CharField(label='Contraseña', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repita Contraseña', widget=forms.PasswordInput)
# usuarios = forms.CharField(label= 'Usuarios', widget=forms.SelectMultiple(choices=RegularUser.objects.all()))
class Meta:
model = AdminUser
fields = ('username',
'email',
'password',
'telefono',
'avatar',
'usuarios',
'groups',)
def clean_password2(self):
# Check that the 2 password entries match
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password2 and password1 != password2:
raise ValueError("Las contraseñas no coinciden")
return password2
# def _save_m2m(self):
# user = super().save(commit=False)
# self.instance.user_set = self.cleaned_data['user']
def save(self, commit=True):
# Save the commit password in hashed form
user = super().save(commit=False)
user.set_password(self.cleaned_data['password1'])
# Set the current User as admin user
user.is_staff = True
if commit:
user.save()
group = Group.objects.get(name="Administradores")
user.groups.add(group)
# group.user_set.add(user)
# group.save()
return user
#receiver(post_save, sender=AdminUser)
def post_save_admin(sender, instance, **kwargs):
if kwargs['created'] and instance.is_staff:
grupo = Group.objects.get(name="Administradores")
grupo.user_set.add(instance)
class AdminChangeForm(forms.ModelForm):
""" A form for updating Administrators. Includes all the fields on the user
, but replaces the password field with admin's password hash display field"""
password = ReadOnlyPasswordHashField()
class Meta:
model = AdminUser
fields = ('username',
'email',
'password',
'first_name',
'last_name',
'descripcion',
'telefono',
'avatar',
'usuarios',
'groups',
)
def clean_password(self):
# Regardless of what the admin provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
class AdminUserAdmin(BaseUserAdmin):
# The forms to add and change admin instances
form = AdminChangeForm
add_form = AdminCreationForm
# The fields to be used in displaying the Admin model.
# These overrides the definitions on the base AdminUserAdmin
# that reference specific fields on auth.User
list_display = ('username', 'email',)
list_filter = ('last_login',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Información Personal', {'fields': ('first_name', 'last_name', 'descripcion', 'avatar', 'telefono',)}),
('Administración', {'fields': ('is_staff', 'usuarios','groups')}),
)
# add_fieldsets is not a standard Modeladmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'email', 'telefono', 'password1', 'password2', 'usuarios','groups')}
),
)
search_fields = ('username',)
ordering = ('username',)
filter_horizontal = ()
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('username', 'email', 'is_staff')
list_filter = ('is_staff',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('first_name', 'last_name', 'descripcion', 'avatar', 'telefono',)}),
('Permissions', {'fields': ('is_staff', 'is_superuser')}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'email', 'telefono', 'password1', 'password2',)}
),
)
search_fields = ('username',)
ordering = ('username',)
filter_horizontal = ()
# Now register the new UserAdmin...
admin.site.register(MyUser, UserAdmin)
admin.site.register(AdminUser, AdminUserAdmin)
# #admin.register(MyUser)
# class MyUserAdmin(admin.ModelAdmin):
# pass
# #admin.register(AdminUser)
# class AdminUserAdmin(admin.ModelAdmin):
# # The forms to add and change Admin instances:
# form = AdminChangeForm
#admin.register(RegularUser)
class RegularUserAdmin(admin.ModelAdmin):
pass
I think the solution must be here, but it doesn't work:
SAVE USER FUNCTION
def save(self, commit=True):
# Save the commit password in hashed form
user = super().save(commit=False)
user.set_password(self.cleaned_data['password1'])
# Set the current User as admin user
user.is_staff = True
if commit:
user.save()
group = Group.objects.get(name="Administradores")
user.groups.add(group)
# group.user_set.add(user)
# group.save()
return user
This is because django admin doesn't call your form's save method with commit=True.
If you really want this to be done only for users saved from the admin then you should override the save_model method on the ModelAdmin. This means that you will need to unregister the UserModelAdmin from django.contrib.admin and create your own UserModelAdmin.
If you want this to be done globally within your application look into the post_save signal.
This is the solution I have found.
#receiver(post_save, sender= AdminUser)
def add_admin_permission(sender, instance, created, **kwargs):
if created:
grupo = Group.objects.get(id=1)
grupo.user_set.add(instance)
Hi I have a rare problem with my custom user for Django. This is my CustomUser code.
class CustomUser(AbstractBaseUser, PermissionsMixin):
""" Custom User model. This class replace the default django user.
"""
nick_validator = [
validators.RegexValidator(re.compile('^[\w.#+\- ]+$'),
'Introduce un nombre de usuario válido',
'invalid')
]
help_texts = {
'nick': '30 caracteres o menos. Caracteres válidos: letas, números'
' y los caracteres #/./ /-/+/_',
'avatar':(
'Selecciona una imágen mayor que %(m)dx%(m)d y menor que '
'%(M)dx%(M)d' % {'m': AVATAR_SIZE_MIN, 'M': AVATAR_SIZE_MAX}
)
}
#Fields
nick = models.CharField(max_length=30, unique=True,
validators=nick_validator,
help_text=help_texts['nick'])
email = models.EmailField('Dirección e-mail', max_length=254, unique=True)
is_active = models.BooleanField('Activo', default=True)
is_staff = models.BooleanField('Está staff', default=False)
date_joined = models.DateTimeField('Fecha de registro', auto_now_add=True)
avatar = models.ImageField(upload_to=getAvatarPath,
help_text=help_texts['avatar'],
default=settings.DEFAULT_AVATAR)
objects = CustomUserManager() #Object which make the users in shell.
USERNAME_FIELD = 'nick' #Field used as nick.
REQUIRED_FIELDS = ['email'] #Required fields for the custom user.
class Meta:
verbose_name = 'Usuario'
verbose_name_plural = 'Usuarios'
def emailUser(self, subject, message, from_email=None):
""" Send an email to the user.
:param subject: Email subject
:param message: Email message
:param from_email: sender email
"""
send_mail(subject, message, from_email, [self.email])
def get_full_name(self):
return '%s %s' % self.nick, self.email
def get_short_name(self):
return self.email
def getUserUrl(self, action=None):
#from django.utils.http import urlquote
kwargs = {'nick': self.nick}
if action!=None:
kwargs['action'] = action
return reverse('users:show_user', kwargs=kwargs)
def getUserUrlComments(self):
return self.getUserUrl('comentarios')
def getUserUrlPosters(self):
return self.getUserUrl('posters')
All correct, no?
When I make a new user using the admin panel show this message.
You can see which appear an error, but it doesn't select any field indicating where is the error. Investigating a bit I changed the admin panel class and I added the field username (A field, which doesn't exists in my Custom User class)
class CustomUserAdmin(UserAdmin):
list_display = ('nick', 'email', 'is_superuser')
readonly_fields = ('date_joined',)
fieldsets = (
('Información general', {'fields': ('username', 'nick', 'email', 'password',
'date_joined', 'groups')}),
('Permisos', {'fields': ('is_active', 'is_staff', 'is_superuser',
'user_permissions')}),
('Información personal', {'fields': ('avatar', 'deleteAvatar')})
)
search_fields = ('nick', 'email')
ordering = ('nick',)
add_fieldsets = (
('Información general', {'fields': ('username', 'nick',
'email', 'password1',
'password2')}),
('Permisos', {'fields': ('is_active', 'is_staff', 'is_superuser')}),
('Información personal', {'fields': ('avatar',)})
)
add_form = CustomUserCreationForm
form = CustomUserChangeForm
I check again and this is the result.
There is a hidden field (username) in my CustomUser. I didn't make this field in my customUser, neither appears in database table. Django add automatically this field. And I don't know how delete this field and use the "nick" field as USERNAME_FIELD. In custom forms this field no appears and i can create Users without problems. But in Panel admin i can't create any user.
I expect that you can solve my problem.
Username is required by default in django users which you are extending. You can check python inheritance.
Basically you have username, email and password fields by default plus the fields you add. Your Nick field is not necessary...that is done by the username already.
So I finally managed to add a location field to my User model and this is the code I have:
model:
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User)
location = models.CharField(('location'),max_length=30, blank=False)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
and admin.py:
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django import forms
from UserProfile.models import UserProfile
from django.contrib.admin.views.main import *
class MyUserCreationForm(UserCreationForm):
username = forms.RegexField(label=("Username"), max_length=30, regex=r'^[\w.#+-]+$', help_text = ("Required. 30 characters or fewer. Letters, digits and #/./+/-/_ only."),error_messages = {'invalid': ("This value may contain only letters, numbers and #/./+/-/_ characters.")})
password1 = forms.CharField(label=("Password"), widget=forms.PasswordInput)
password2 = forms.CharField(label=("Password confirmation"), widget=forms.PasswordInput, help_text = ("Enter the same password as above, for verification."))
email = forms.EmailField(label=("Email address"))
class Meta:
model = User
fields = ("username",)
def clean_username(self):
username = self.cleaned_data["username"]
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError(("A user with that username already exists."))
def clean_email(self):
email = self.cleaned_data["email"]
if email == "":
raise forms.ValidationError((""))
return email
def clean_password2(self):
password1 = self.cleaned_data.get("password1", "")
password2 = self.cleaned_data["password2"]
if password1 != password2:
raise forms.ValidationError(("The two password fields didn't match."))
return password2
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class MyUserChangeForm(UserChangeForm):
username = forms.RegexField(label=("Username"), max_length=30, regex=r'^[\w.#+-]+$',
help_text = ("Required. 30 characters or fewer. Letters, digits and #/./+/-/_ only."),
error_messages = {'invalid': ("This value may contain only letters, numbers and #/./+/-/_ characters.")})
location = forms.CharField(label=("Location"),max_length=30)
class Meta:
model = User
def __init__(self, *args, **kwargs):
super(UserChangeForm, self).__init__(*args, **kwargs)
f = self.fields.get('user_permissions', None)
if f is not None:
f.queryset = f.queryset.select_related('content_type')
class CustomUserAdmin(UserAdmin):
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'email', 'password1', 'password2')}
),
)
fieldsets = (
(None, {'fields': ('username', 'password')}),
(('Personal info'), {'fields': ('first_name', 'last_name', 'email', 'location')}),
(('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser', 'user_permissions')}),
(('Important dates'), {'fields': ('last_login', 'date_joined')}),
(('Groups'), {'fields': ('groups',)}),
)
#list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'location')
add_form = MyUserCreationForm
form = MyUserChangeForm
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
When I tried creating a user it finally didn't error. But when I went to edit the information about the user, the location field was empty. I checked the database manually using sqlite database browser. And I assumed by creating a UserProfile would add extra tables to the database, but it didn't. What I want is for the location field to be trated just like the email field or the username or any other information stored about the user.
You don't add fields to the old model this way, you're creating a new one that's associated with it. Your data will be in app_userprofile table, and you can access that instance (to save that location or whatever) via user.get_profile(). You can't use straightforward ModelForm for that, I'm afraid, you need to handle the profile yourself.