NoneType error when saving UserProfileAdmin after Django 4.1 update
PetrDlouhy opened this issue · comments
Petr Dlouhý commented
What happened?
When I press save button on my UserProfile admin page, the following error is thrown:
Traceback (most recent call last):
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/core/handlers/exception.py", line 56, in inner
response = get_response(request)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/sentry_sdk/integrations/django/views.py", line 85, in sentry_wrapped_callback
return callback(request, *args, **kwargs)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/contrib/admin/options.py", line 686, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/utils/decorators.py", line 134, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/views/decorators/cache.py", line 62, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/contrib/admin/sites.py", line 242, in inner
return view(request, *args, **kwargs)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/contrib/admin/options.py", line 1894, in change_view
return self.changeform_view(request, object_id, form_url, extra_context)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/utils/decorators.py", line 46, in _wrapper
return bound_method(*args, **kwargs)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/utils/decorators.py", line 134, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/contrib/admin/options.py", line 1751, in changeform_view
return self._changeform_view(request, object_id, form_url, extra_context)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/contrib/admin/options.py", line 1797, in _changeform_view
form_validated = form.is_valid()
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/forms/forms.py", line 205, in is_valid
return self.is_bound and not self.errors
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/forms/forms.py", line 200, in errors
self.full_clean()
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/forms/forms.py", line 439, in full_clean
self._post_clean()
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/forms/models.py", line 492, in _post_clean
self.instance.full_clean(exclude=exclude, validate_unique=False)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/db/models/base.py", line 1475, in full_clean
self.validate_constraints(exclude=exclude)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/db/models/base.py", line 1423, in validate_constraints
constraint.validate(model_class, self, exclude=exclude, using=using)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/db/models/constraints.py", line 365, in validate
if (self.condition & Exists(queryset.filter(self.condition))).check(
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/django/db/models/query_utils.py", line 141, in check
return compiler.execute_sql(SINGLE) is not None
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/cachalot/monkey_patch.py", line 37, in inner
return original(compiler, *args, **kwargs)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/cachalot/monkey_patch.py", line 92, in inner
table_cache_keys = _get_table_cache_keys(compiler)
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/cachalot/utils.py", line 276, in _get_table_cache_keys
for t in _get_tables(db_alias, compiler.query, compiler)]
File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.10/site-packages/cachalot/utils.py", line 220, in _get_tables
tables.add(query.get_meta().db_table)
AttributeError: 'NoneType' object has no attribute 'db_table'
The same error occurs on two more of my admin pages (out of many more).
The exception is not thrown from Django 4.0, but is thrown from Django 4.1.
Also if I remove cachalot
from INSTALLED_APPS
the problem disapears.
What should've happened instead?
The changes should be saved.
Steps to reproduce
Configuration:
- Django-cachalot 5.2.0
- Django 4.1
- PostgreSQL database
- System:
Linux petr-ws 5.15.0-58-generic #64-Ubuntu SMP Thu Jan 5 11:43:13 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
- Create UserProfile model with some UniqueConstraint, e.g.:
class UserProfile(AbstractUser):
class Meta:
constraints = [
UniqueConstraint(
Lower("email").desc(), # type: ignore
condition=Q(deleted_at=None),
name="unique_email",
)
]
- Go to http://localhost:8000/admin/accounts/userprofile/xxxx/change/
- Press save
More details
What I have already find out is that the query with None
in query.get_meta()
is following:
SELECT 1 AS "_check" WHERE COALESCE((NULL IS NULL AND EXISTS(SELECT 1 AS "a" FROM "accounts_userprofile" U0 WHERE (LOWER(U0."email") = (LOWER()) AND NOT (U0."id" = 897) AND U0."deleted_at" IS NULL) LIMIT 1)), True)