#24346: AuthRouter docs lead to AttributeError: 'NoneType' object has no
attribute
'_meta' with 0002_remove_content_type_name
-------------------------------+-----------------------
Reporter: pzrq | Owner: nobody
Type: Bug | Status: new
Component: Documentation | Version: 1.8alpha1
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+-----------------------
#22583 passes `model=None` into `allow_migrate(db, model, **hints)`:
https://github.com/django/django/blob/8f4877c89d0f28e289399fbb46357623a49e7eb0/django/db/migrations/operations/special.py#L174
#24099 introduced a `0002_remove_content_type_name` migration which uses
this code path:
https://github.com/django/django/blob/b4ac23290772e0c11379eb2dfb81c750b7052b66/django/contrib/contenttypes/migrations/0002_remove_content_type_name.py
When combined with the documented `AuthRouter` example:
https://docs.djangoproject.com/en/1.8/topics/db/multi-db/#an-example
This causes a stacktrace like the following in downstream projects:
{{{
$ ./manage.py test --verbosity=2
Creating test database for alias 'default' (':memory:')...
...
Running migrations:
Rendering model states... DONE
...
Applying contenttypes.0002_remove_content_type_name...Traceback (most
recent call last):
File "./manage.py", line 20, in <module>
execute_from_command_line(sys.argv)
File "/Users/pzrq/Projects/django/django/core/management/__init__.py",
line 338, in execute_from_command_line
utility.execute()
File "/Users/pzrq/Projects/django/django/core/management/__init__.py",
line 330, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File
"/Users/pzrq/Projects/django/django/core/management/commands/test.py",
line 30, in run_from_argv
super(Command, self).run_from_argv(argv)
File "/Users/pzrq/Projects/django/django/core/management/base.py", line
390, in run_from_argv
self.execute(*args, **cmd_options)
File
"/Users/pzrq/Projects/django/django/core/management/commands/test.py",
line 74, in execute
super(Command, self).execute(*args, **options)
File "/Users/pzrq/Projects/django/django/core/management/base.py", line
441, in execute
output = self.handle(*args, **options)
File
"/Users/pzrq/Projects/django/django/core/management/commands/test.py",
line 90, in handle
failures = test_runner.run_tests(test_labels)
File "/Users/pzrq/Projects/django/django/test/runner.py", line 210, in
run_tests
old_config = self.setup_databases()
File "/Users/pzrq/Projects/django/django/test/runner.py", line 166, in
setup_databases
**kwargs
File "/Users/pzrq/Projects/django/django/test/runner.py", line 370, in
setup_databases
serialize=connection.settings_dict.get("TEST", {}).get("SERIALIZE",
True),
File "/Users/pzrq/Projects/django/django/db/backends/base/creation.py",
line 369, in create_test_db
test_flush=True,
File "/Users/pzrq/Projects/django/django/core/management/__init__.py",
line 120, in call_command
return command.execute(*args, **defaults)
File "/Users/pzrq/Projects/django/django/core/management/base.py", line
441, in execute
output = self.handle(*args, **options)
File
"/Users/pzrq/Projects/django/django/core/management/commands/migrate.py",
line 213, in handle
executor.migrate(targets, plan, fake=options.get("fake", False))
File "/Users/pzrq/Projects/django/django/db/migrations/executor.py",
line 93, in migrate
self.apply_migration(states[migration], migration, fake=fake)
File "/Users/pzrq/Projects/django/django/db/migrations/executor.py",
line 129, in apply_migration
state = migration.apply(state, schema_editor)
File "/Users/pzrq/Projects/django/django/db/migrations/migration.py",
line 110, in apply
operation.database_forwards(self.app_label, schema_editor, old_state,
project_state)
File
"/Users/pzrq/Projects/django/django/db/migrations/operations/special.py",
line 174, in database_forwards
if self.allowed_to_migrate(schema_editor.connection.alias, None,
hints=self.hints):
File
"/Users/pzrq/Projects/django/django/db/migrations/operations/base.py",
line 109, in allowed_to_migrate
return router.allow_migrate(connection_alias, model, **(hints or {}))
File "/Users/pzrq/Projects/django/django/db/utils.py", line 334, in
allow_migrate
allow = method(db, model, **hints)
File
"/Users/pzrq/Projects/mathspace/msproblem/core/database_routers.py", line
67, in allow_migrate
elif model._meta.app_label in APP_LABELS:
AttributeError: 'NoneType' object has no attribute '_meta'
}}}
This is documented here:
https://docs.djangoproject.com/en/1.8/releases/1.8/#miscellaneous
> The migration operations RunPython and RunSQL now call the
allow_migrate() method of database routers. In these cases the model
argument of allow_migrate() is set to None, so the router must properly
handle this value.
So I guess the fix is to update the docs to be consistent with the
previously committed changes, e.g.
{{{
class AuthRouter(object):
...
def allow_migrate(self, db, model=None, **hints):
"""
Make sure the auth app only appears in the 'auth_db'
database.
"""
if model is None:
# Handle RunPython or RunSQL
return db == 'auth_db'
if db == 'auth_db':
return model._meta.app_label == 'auth'
elif model._meta.app_label == 'auth':
return False
return None
}}}
Will add a Github PR for that shortly.
--
Ticket URL: <https://code.djangoproject.com/ticket/24346>
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 [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/047.c5db0e893adf68cf88e3c1c65e520f48%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.