#26686 closed Bug (fixed)
django.core.checks.model_checks _check_lazy_references raises TypeError with NoneType model_key
Reported by: | Brett Haydon | Owned by: | nobody |
---|---|---|---|
Component: | Core (System checks) | Version: | 1.10 |
Severity: | Release blocker | Keywords: | |
Cc: | Alex Hill | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Steps for reproduction
Create poll app or any model
inherit model from django-model-utils model_utils.models.TimeStampedModel
./manage.py makemigrations
In the model import process (None, 'statusmodel') erroneously gets added to the django.core.registry.App._pending_operations. StatusModel is a model in model_utils.models but is not imported into the poll app.
django.core.checks.model_checks._check_lazy_references iterates over the model_key in _pending_operations but can't handle a model_key of NoneType so raises the TypeError.
Being a defaultdict _pending_operations seems the point of weakness here.
Attachments (1)
Change History (8)
comment:1 by , 8 years ago
by , 8 years ago
Attachment: | django-typeerror.zip added |
---|
comment:2 by , 8 years ago
Attached my throwaway project. model-utils isn't in installed apps (it doesn't need to be)
pip install django-model-utils (and django 1.10a).
./manage.py makemigrations demoapp
Traceback (most recent call last): File "./manage.py", line 22, in <module> execute_from_command_line(sys.argv) File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/management/__init__.py", line 367, in execute_from_command_line utility.execute() File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/management/__init__.py", line 359, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/management/base.py", line 305, in run_from_argv self.execute(*args, **cmd_options) File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/management/base.py", line 353, in execute self.check() File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/management/base.py", line 385, in check include_deployment_checks=include_deployment_checks, File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/management/base.py", line 372, in _run_checks return checks.run_checks(**kwargs) File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/checks/registry.py", line 81, in run_checks new_errors = check(app_configs=app_configs) File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/checks/model_checks.py", line 156, in check_lazy_references return _check_lazy_references(apps) File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/checks/model_checks.py", line 151, in _check_lazy_references )), key=lambda error: error.msg) File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/checks/model_checks.py", line 150, in <genexpr> for func in apps._pending_operations[model_key] File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/checks/model_checks.py", line 145, in build_error return error_fn(model_key, func, args, keywords) if error_fn else None File "/Users/bretth/projects/_virtualenvs/django-typeerror/lib/python3.5/site-packages/django/core/checks/model_checks.py", line 117, in signal_connect_error 'model': '.'.join(model_key or ''), TypeError: sequence item 0: expected str instance, NoneType found
comment:3 by , 8 years ago
Cc: | added |
---|---|
Severity: | Normal → Release blocker |
Triage Stage: | Unreviewed → Accepted |
Obviously it would be better not to crash, however, isn't it a requirement to put model_utils
in INSTALLED_APPS
if you want to use any models from it?
After doing that with the sample project, this error is reported, model_utils.fields: (signals.E001) Bound method 'MonitorField._save_initial' was connected to the 'post_init' signal with a lazy reference to the sender 'model_utils.statusmodel', but app 'model_utils' doesn't provide model 'statusmodel'.
I'm not sure if it's correct -- the model is there, although it's abstract (no problems with Django 1.9).
comment:4 by , 8 years ago
If you're only using abstract models, you shouldn't need to add to INSTALLED_APPS
. This is explicitly allowed in models/base.py
I've found a bug in ModelSignal
. It contains a conditional branch for senders of type Model
, but it should be checking for BaseModel
, since model signals are used with classes, not instances. Fixing that fixes this problem.
The long version of what's happening is:
- _lazy_model_operation works by waiting for models to be registered
- abstract models are never registered with the app registry, so their operations will remain forever pending
- StatusModel is abstract, and has a MonitorField
- MonitorField connects to the `post_init` signal in its `contribute_to_class()` method
- signals use _lazy_model_operation as of 1.10
- the bug means _lazy_model_operation is used by the
post_init
signal even when a model class is provided, not a string.
Incidentally, we currently happily register model signals with abstract senders even though they'll never be sent. Since perfectly reasonable code like the linked code in django-model-utils does this, I don't think a warning is appropriate. I think we should just ignore them explicitly in ModelSignal and document that behaviour. Thoughts?
comment:5 by , 8 years ago
Has patch: | set |
---|
Pull request at https://github.com/django/django/pull/6678
Do you have
model_utils
inINSTALLED_APPS
? Could you upload the minimal project to reproduce?