I am trying to extend Django's user model as per
https://docs.djangoproject.com/en/1.9/topics/auth/customizing/
Now i can add a new field that i want to be associated with each user. But the problem is, i cannot add a non-admin user. If i add a user and dont make them the admin, then the login fails
but if i log in as any admin user, i clearly see
Why is my application only allowing admins to log in? Do i have to create a separate login screen for non admin users?
here is my models.py
from django.db import models
from django.contrib.auth.models import (
User, BaseUserManager, AbstractBaseUser
)
'''
class UserProfile(models.Model):
appcodes = models.TextField()
user = models.ForeignKey(User, unique=True)
'''
class AppCodeUserManager(BaseUserManager):
def create_user(self, email, appcode, password=None):
"""
Creates and saves a User with the given email, appcode and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
appcodes=appcode
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, appcode, password):
"""
Creates and saves a superuser with the given email, appcode and password.
"""
print("Creating superuser...")
user = self.create_user(email,
password=password,
appcodes=appcode
)
user.is_admin = True
user.save(using=self._db)
return user
class AppCode(models.Model):
appcode_name = models.CharField(max_length=255,unique=True)
class AppCodeUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
appcodes = models.TextField()#CharField(max_length=255,unique=True,default="RIK0")#models.ManyToManyField(AppCode)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = AppCodeUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['appcodes']
def get_appcodes(self):
return ", ".join([p.appcode_name for p in self.appcodes.all()])
get_appcodes.short_description = 'Appcodes'
get_appcodes.allow_tags = True
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __str__(self): # __unicode__ on Python 2
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
all i want to do is add a TextField() for each user. This field will be named appcodes
and here is my 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 .models import AppCodeUser
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)
appcodes=forms.TextInput
class Meta:
model = AppCodeUser
fields = ('email', 'appcodes')
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(UserCreationForm, self).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 = AppCodeUser
fields = ('email', 'password', 'appcodes', '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','appcodes','is_admin','is_active')
list_filter = ('is_admin',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Appcode info', {'fields': ('appcodes',)}),
('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', 'appcodes', 'password1', 'password2')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
# Now register the new UserAdmin...
admin.site.register(AppCodeUser, UserAdmin)
# ... and, since we're not using Django's built-in permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)
and in my settings.py i have
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'hdfsStats.apps.HdfsstatsConfig',
]
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
AUTH_USER_MODEL = 'hdfsStats.AppCodeUser'
rest are default values i guess
Related
I'm trying to Override the user model to make usernames case insensitive and allow semicolons. I haven't added the code for semicolons yet. I am getting a matching query error while trying to create a superuser.
When I run python manage.py createsuperuser I get a matching query error
Here is my code
models.py
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser, BaseUserManager
)
class UserManager(BaseUserManager):
def get_by_natural_key(self, username):
return self.get(**{self.model.USERNAME_FIELD + '__iexact': username})
def create_user(self, username, password=None, is_active=True, is_staff=False, is_admin=False):
if not username:
raise ValueError("Users must have an username address")
if not password:
raise ValueError("Users must have a password")
user_obj = self.model(
username = self.get_by_natural_key(username)
)
user_obj.set_password(password) # change user password
user_obj.staff = is_staff
user_obj.admin = is_admin
user_obj.active = is_active
user_obj.save(using=self._db)
return user_obj
def create_staffuser(self, username, password=None):
user = self.create_user(
username,
password=password,
is_staff=True
)
return user
def create_superuser(self, username, password=None):
user = self.create_user(
username,
password=password,
is_staff=True,
is_admin=True
)
return user
class User(AbstractBaseUser):
username = models.CharField(max_length=255, unique=True)
#full_name = models.CharField(max_length=255, blank=True, null=True)
active = models.BooleanField(default=True) # can login
staff = models.BooleanField(default=False) # staff user non superuser
admin = models.BooleanField(default=False) # superuser
timestamp = models.DateTimeField(auto_now_add=True)
# confirm = models.BooleanField(default=False)
# confirmed_date = models.DateTimeField(default=False)
USERNAME_FIELD = 'username' #username
# USERNAME_FIELD and password are required by default
REQUIRED_FIELDS = [] #['full_name'] #python manage.py createsuperuser
objects = UserManager()
def __str__(self):
return self.username
def get_full_name(self):
return self.username
def get_short_name(self):
return self.username
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
def is_staff(self):
return self.staff
def is_admin(self):
return self.admin
def is_active(self):
return self.active
admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
User = get_user_model()
class UserAdmin(BaseUserAdmin):
list_display = ('username', 'admin')
list_filter = ('admin', 'staff', 'active')
fieldsets = (
(None, {'fields': ('username', 'password')}),
('Personal info', {'fields': ()}),
('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': ('username', 'password1', 'password2')}
),
)
search_fields = ('username',)
ordering = ('username',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
Here is the error that I'm getting
account.models.DoesNotExist: User matching query does not exist.
I am fairly new to Django and set up a custom user model with token authentication. Now I am trying to add the possibility of adding users to user groups from the backend in order to specify permissions. However, I dont seem to be able to get past this error. I am using Python 3.7 and Django 2.2.6. Appreciate your help!
The error:
File "/Users/.../Dev/.../account/models.py", line 114, in save_m2m
self.instance.user_set.set(self.cleaned_data['users'])
AttributeError: 'Group' object has no attribute 'user_set'
my models.py:
from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
from django import forms
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.contrib.auth.models import Group
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not email:
raise ValueError("Users must have an email address")
if not username:
raise ValueError("Users must have a username")
user = self.model(
email=self.normalize_email(email),
username=username,
)
group = Group.objects.all()
user.groups.add(group)
# group.user_set.add(user)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user = self.create_user(
email=self.normalize_email(email),
password=password,
username=username,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
date_joined = models.DateTimeField(
verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
plan_choices = [("P", "Pro"), ("B", "Basic"),
("F", "Free"), ("S", "Staff"), ("A", "Admin")]
plan = models.CharField(choices=plan_choices, default="F", max_length=1)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = MyAccountManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
# if new user is registered to the server, a new token is generated
Token.objects.create(user=instance)
User = get_user_model()
# Create ModelForm based on the Group model.
# class GroupAdminForm(forms.ModelForm):
# class Meta:
# model = Group
# exclude = []
# Add the users field.
# users = forms.ModelMultipleChoiceField(
# queryset=User.objects.all(),
# required=False,
# widget=FilteredSelectMultiple('users', False)
# )
# def __init__(self, *args, **kwargs):
# super(GroupAdminForm, self).__init__(*args, **kwargs)
# if self.instance.pk:
# self.fields['users'].initial = self.instance.user_set.all()
# def save_m2m(self):
# self.instance.user_set.set(self.cleaned_data['users'])
# def save(self, *args, **kwargs):
# instance = super(GroupAdminForm, self).save()
# self.save_m2m()
# return instance
my admin.py:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from account.models import Account
from django.contrib.auth.models import Group
# from .models import GroupAdminForm
class AccountAdmin(UserAdmin):
list_display = ('email', 'username', 'date_joined',
'last_login', 'is_admin', 'is_staff', 'plan')
search_fields = ('email', 'username')
readonly_fields = ('date_joined', 'last_login')
filter_horizontal = ()
list_filter = ()
fieldsets = ()
admin.site.register(Account, AccountAdmin)
# Unregister the original Group admin.
# admin.site.unregister(Group)
# class GroupAdmin(admin.ModelAdmin):
# form = GroupAdminForm
# filter_horizontal = ['permissions']
# admin.site.register(Group, GroupAdmin)
UPDATE
I adjusted the code to no longer overwrite the Group class, and instead extend PermissionsMixin in my Account class. This allowed me to see permission groups and specific groups on a per user basis, however when these are applied, there seems to be no effect at all. I still have the same access as before. What am I missing?
group = Group.objects.all() is a queryset. user_set can be accessed from a Group instance.
Also, add the possibility of adding users to user groups from the backend - you don't need to do that. Once the user is created, you can always add the user to a particular group by:
groups = Group.objects.filter(...) # get groups you want to add the user to
user.groups.add(*groups)
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)
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.