Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#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)

django-typeerror.zip (9.5 KB ) - added by Brett Haydon 8 years ago.

Download all attachments as: .zip

Change History (8)

comment:1 by Tim Graham, 8 years ago

Do you have model_utils in INSTALLED_APPS? Could you upload the minimal project to reproduce?

by Brett Haydon, 8 years ago

Attachment: django-typeerror.zip added

comment:2 by Brett Haydon, 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 Tim Graham, 8 years ago

Cc: Alex Hill added
Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

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 Alex Hill, 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:

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 Alex Hill, 8 years ago

Has patch: set

comment:6 by Tim Graham <timograham@…>, 8 years ago

Resolution: fixed
Status: newclosed

In 08014fe7:

Fixed #26686 -- Fixed crash when registering model signals with abstract senders.

comment:7 by Tim Graham <timograham@…>, 8 years ago

In 85d2b80d:

[1.10.x] Fixed #26686 -- Fixed crash when registering model signals with abstract senders.

Backport of 08014fe75b4fc379523f340191a02147ec35f7a3 from master

Note: See TracTickets for help on using tickets.
Back to Top