Trying to set up custom user model on the start of django project, but i am facing a recurrent problem that i have only been able to patch, that now is affecting the changepassword of admin interface. On change password form submit, it crashes with error:
AttributeError at /admin/custom_users/customuser/7/password/
'NoneType' object has no attribute 'strip'
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/admin/custom_users/customuser/7/password/
Django Version: 2.2
Python Version: 3.7.3
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'cashflow.apps.CashflowConfig',
'custom_users.apps.CustomUsersConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/connection_cext.py" in cmd_query
395. raw_as_string=raw_as_string)
During handling of the above exception (Column 'is_superuser' cannot be null), another exception occurred:
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/base.py" in _execute_wrapper
168. return method(query, args)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/cursor_cext.py" in execute
266. raw_as_string=self._raw_as_string)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/connection_cext.py" in cmd_query
398. sqlstate=exc.sqlstate)
During handling of the above exception (1048 (23000): Column 'is_superuser' cannot be null), another exception occurred:
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/backends/utils.py" in execute
99. return super().execute(sql, params)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/backends/utils.py" in execute
67. return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/backends/utils.py" in _execute_with_wrappers
76. return executor(sql, params, many, context)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/backends/utils.py" in _execute
84. return self.cursor.execute(sql, params)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/base.py" in execute
218. return self._execute_wrapper(self.cursor.execute, query, new_args)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/base.py" in _execute_wrapper
174. utils.IntegrityError(err.msg), sys.exc_info()[2])
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/utils/six.py" in reraise
683. raise value.with_traceback(tb)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/base.py" in _execute_wrapper
168. return method(query, args)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/cursor_cext.py" in execute
266. raw_as_string=self._raw_as_string)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/connection_cext.py" in cmd_query
398. sqlstate=exc.sqlstate)
During handling of the above exception (Column 'is_superuser' cannot be null), another exception occurred:
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/cursor_cext.py" in statement
606. return self._executed.strip().decode('utf8')
During handling of the above exception ('NoneType' object has no attribute 'strip'), another exception occurred:
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/core/handlers/exception.py" in inner
34. response = get_response(request)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
115. response = self.process_exception_by_middleware(e, request)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
113. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/utils/decorators.py" in _wrapped_view
142. response = view_func(request, *args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
44. response = view_func(request, *args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/contrib/admin/sites.py" in inner
223. return view(request, *args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/utils/decorators.py" in _wrapper
45. return bound_method(*args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/views/decorators/debug.py" in sensitive_post_parameters_wrapper
76. return view(request, *args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/contrib/auth/admin.py" in user_change_password
141. form.save()
File "/home/mh/devel/dreamit_control/dcontrol/custom_users/forms.py" in save
32. self.user.save()
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/contrib/auth/base_user.py" in save
66. super().save(*args, **kwargs)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/base.py" in save
741. force_update=force_update, update_fields=update_fields)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/base.py" in save_base
779. force_update, using, update_fields,
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/base.py" in _save_table
851. forced_update)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/base.py" in _do_update
900. return filtered._update(values) > 0
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/query.py" in _update
760. return query.get_compiler(self.db).execute_sql(CURSOR)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
1426. cursor = super().execute_sql(result_type)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
1097. cursor.execute(sql, params)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/django/db/backends/utils.py" in execute
103. sql = self.db.ops.last_executed_query(self.cursor, sql, params)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/operations.py" in last_executed_query
127. return force_text(cursor.statement, errors='replace')
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/django/base.py" in __getattr__
230. return getattr(self.cursor, attr)
File "/home/mh/devel/dreamit_control/env/lib/python3.7/site-packages/mysql/connector/cursor_cext.py" in statement
608. return self._executed.strip()
Exception Type: AttributeError at /admin/custom_users/customuser/7/password/
Exception Value: 'NoneType' object has no attribute 'strip'
on stack trace, i can see that the problem is that is_staff=NULL and is_superuser=NULL on the attempted query.
I dont know why django passes this parameters as null on passwordchange since they are set to false on model and nowhere are they as fields on the CustomUserPassForm. Had this same issue on user change form, but after adding fieldsets to CustomUserAdmin(UserAdmin) class, i was able to edit a user. (as the is_superuser and is_staff input checkboxes appeared on form in html)
models.py
class CustomUserManager(BaseUserManager):
def create_user(self, email, password, **extra_fields):
if not email:
raise ValueError('correo es obligatorio')
email = self.normalize_email(email)
extra_fields.setdefault('is_superuser', False)
extra_fields.setdefault('is_staff', False)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('superuser must have is_staff=True')
if extra_fields.get('is_superuser') is not True:
raise ValueError('superuser musthave is_superuser=True')
return self.create_user(email, password, **extra_fields)
class CustomUser(AbstractUser, PermissionsMixin):
cargo = models.TextField(max_length=50, null=True)
rut = models.IntegerField(null=True)
DIGITO_VERIFICADOR_CHOICES = (
('1','1'),
('2','2'),
('3','3'),
('4','4'),
('5','5'),
('6','6'),
('7','7'),
('8','8'),
('9','9'),
('0','0'),
('K','K')
)
digito_verificador = models.CharField(max_length=1, choices=DIGITO_VERIFICADOR_CHOICES, null=True)
nombre = models.CharField(max_length=25, default="john")
apellido = models.CharField(max_length=25, default="doe")
email = models.EmailField(verbose_name='correo', max_length=255, unique=True)
username = models.TextField(max_length=255, null=True)
is_superuser = models.BooleanField(default=False, blank=True)
is_staff = models.BooleanField(default=False, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
forms.py
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = get_user_model()
fields = ['email', 'rut', 'digito_verificador',]
class CustomUserChangeForm(UserChangeForm):
rut = forms.IntegerField(min_value=1000000)
#is_superUser = forms.BooleanField()
class Meta:
model = get_user_model()
fields = ['rut', 'digito_verificador',]
#['email', 'is_superuser','is_staff' ]
class CustomUserPassForm(AdminPasswordChangeForm):
# is_staff = forms.BooleanField(initial=False)
# is_superuser = forms.BooleanField(initial=False)
#fields = ['is_staff','is_superuser']
def save(self, commit=True):
password = self.cleaned_data["password1"]
self.user.set_password(password)
print(self.user)
if commit:
self.user.save()
return self.user
admin.py
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
change_password_form = CustomUserPassForm
model = get_user_model()
list_display = ['email', ]
fieldsets = (
(None, {'fields': ('email', 'password')}),
('personal info',{'fields': ('nombre', 'apellido',('rut','digito_verificador'))}),
('permissions', {'fields':('is_superuser', 'is_staff')})
)
add_fieldsets = (
(None, {
'classes':('wide',),
'fields':('email', 'password1', 'password2'),
}
),
)
admin.site.register(CustomUser, CustomUserAdmin)
Have been two days reading tutorials and documentation, including official django guide, all which leave out any information about implementation of change_password_form.