#32897: create_user() does not raise ValidationError ----------------------------------------+------------------------ Reporter: adamckay | Owner: nobody Type: Bug | Status: new Component: contrib.auth | Version: 3.2 Severity: Normal | Keywords: Triage Stage: Unreviewed | Has patch: 0 Needs documentation: 0 | Needs tests: 0 Patch needs improvement: 0 | Easy pickings: 0 UI/UX: 0 | ----------------------------------------+------------------------ The `django.contrib.auth.models.UserManager.create_user()` function does not perform validation checking of the user object prior to saving to the database.
The documentation ([https://docs.djangoproject.com/en/3.2/ref/contrib/auth/#django.contrib.auth.models.UserManager.create_user]) implies this is the canonical way to create a user object and indeed it performs functions to normalize the email address and username as well as setting an unusable password, however the object is not validated using `full_clean()` which results in an object that has validation errors attempting to be committed to the database raising an `IntegrityError` rather than a `ValidationError`. This impacts the ability to add errors to any forms which use `create_user()` as the `IntegrityError` does not return a user-friendly message, nor is it applied to a field element. Reproduction steps in a Django shell: {{{ >>> from django.contrib.auth.models import User >>> User.objects.create_user('example') <User: example> >>> User.objects.create_user('example') Traceback (most recent call last): File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/backends/utils.py", line 84, in _execute return self.cursor.execute(sql, params) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/backends/sqlite3/base.py", line 423, in execute return Database.Cursor.execute(self, query, params) sqlite3.IntegrityError: UNIQUE constraint failed: auth_user.username The above exception was the direct cause of the following exception: Traceback (most recent call last): File "<console>", line 1, in <module> File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/contrib/auth/models.py", line 152, in create_user return self._create_user(username, email, password, **extra_fields) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/contrib/auth/models.py", line 146, in _create_user user.save(using=self._db) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/contrib/auth/base_user.py", line 67, in save super().save(*args, **kwargs) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/models/base.py", line 726, in save self.save_base(using=using, force_insert=force_insert, File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/models/base.py", line 763, in save_base updated = self._save_table( File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/models/base.py", line 868, in _save_table results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/models/base.py", line 906, in _do_insert return manager._insert( File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/models/manager.py", line 85, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/models/query.py", line 1270, in _insert return query.get_compiler(using=using).execute_sql(returning_fields) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/models/sql/compiler.py", line 1416, in execute_sql cursor.execute(sql, params) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/backends/utils.py", line 98, in execute return super().execute(sql, params) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/backends/utils.py", line 66, in execute return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers return executor(sql, params, many, context) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/backends/utils.py", line 84, in _execute return self.cursor.execute(sql, params) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/utils.py", line 90, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/backends/utils.py", line 84, in _execute return self.cursor.execute(sql, params) File "/.pyenv/versions/38-django-core/lib/python3.8/site- packages/django/db/backends/sqlite3/base.py", line 423, in execute return Database.Cursor.execute(self, query, params) django.db.utils.IntegrityError: UNIQUE constraint failed: auth_user.username }}} -- Ticket URL: <https://code.djangoproject.com/ticket/32897> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/051.f2a22f149fef5094b18a6b4874e83600%40djangoproject.com.