#33280: [bug] migration don't work with multiple databases (sometimes)
-------------------------------------+-------------------------------------
               Reporter:             |          Owner:  nobody
  razielvamp666                      |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  2.2
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:  orm migration
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 My configuration is:


 {{{
 python 3.7.1
 }}}


 {{{
 Django==2.2.24
 django-axes==5.16.0
 django-bootstrap-modal-forms==1.3.1
 django-celery-results==1.0.4
 django-cors-headers==3.1.1
 django-database-view==0.3.0
 django-debug-toolbar==1.11
 django-dynamic-db-router==0.3.0
 django-ipware==3.0.7
 django-redis-cache==3.0.0
 django-redis-sessions==0.6.2
 django-ses==1.0.3
 django-storages==1.12.3
 django-taggit==0.24.0
 djangorestframework==3.12.4
 pytest-django==4.4.0
 }}}

 I using Django with multiple databases and default DB is not set for
 security reasons (I prefer to get error if Django will fallback to
 `default` connection, because it means that current tenant DB is not used
 for some reasons). so `default` connection is empty (`{}`).

 When I run `python manage.py migrate --database=some_db_name`

 I've get error:

 {{{
   Applying app_name.0154_migration_name...Traceback (most recent call
 last):
   File "manage.py", line 41, in <module>
     execute_from_command_line(sys.argv)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/core/management/__init__.py", line 381, in
 execute_from_command_line
     utility.execute()
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/core/management/__init__.py", line 375, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/core/management/base.py", line 323, in run_from_argv
     self.execute(*args, **cmd_options)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/core/management/base.py", line 364, in execute
     output = self.handle(*args, **options)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/core/management/base.py", line 83, in wrapped
     res = handle_func(*args, **kwargs)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/core/management/commands/migrate.py", line 234, in handle
     fake_initial=fake_initial,
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/migrations/executor.py", line 117, in migrate
     state = self._migrate_all_forwards(state, plan, full_plan, fake=fake,
 fake_initial=fake_initial)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/migrations/executor.py", line 147, in
 _migrate_all_forwards
     state = self.apply_migration(state, migration, fake=fake,
 fake_initial=fake_initial)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/migrations/executor.py", line 245, in apply_migration
     state = migration.apply(state, schema_editor)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/migrations/migration.py", line 124, in apply
     operation.database_forwards(self.app_label, schema_editor, old_state,
 project_state)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/dbview/helpers.py", line 21, in database_forwards
     self._create_standard_view(model, schema_editor)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/dbview/helpers.py", line 60, in _create_standard_view
     qs = str(model.view())
   File
 "/user/code/genki_labo/orm_django/models/novel_coronavirus_vaccine.py",
 line 136, in view
     return str(qs.query)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/models/sql/query.py", line 265, in __str__
     sql, params = self.sql_with_params()
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/models/sql/query.py", line 273, in sql_with_params
     return self.get_compiler(DEFAULT_DB_ALIAS).as_sql()
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/models/sql/compiler.py", line 474, in as_sql
     extra_select, order_by, group_by = self.pre_sql_setup()
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/models/sql/compiler.py", line 54, in pre_sql_setup
     self.setup_query()
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/models/sql/compiler.py", line 45, in setup_query
     self.select, self.klass_info, self.annotation_col_map =
 self.get_select()
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/models/sql/compiler.py", line 254, in get_select
     sql, params = self.compile(col, select_format=True)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/models/sql/compiler.py", line 405, in compile
     sql, params = node.as_sql(self, self.connection)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/models/expressions.py", line 737, in as_sql
     return "%s.%s" % (qn(self.alias), qn(self.target.column)), []
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/models/sql/compiler.py", line 396, in
 quote_name_unless_alias
     r = self.connection.ops.quote_name(name)
   File "/user/.pyenv/versions/gl/lib/python3.7/site-
 packages/django/db/backends/dummy/base.py", line 20, in complain
     raise ImproperlyConfigured("settings.DATABASES is improperly
 configured. "
 django.core.exceptions.ImproperlyConfigured: settings.DATABASES is
 improperly configured. Please supply the ENGINE value. Check settings
 documentation for more details.
 }}}

 You can see that problem is here:

 {{{
 return self.get_compiler(DEFAULT_DB_ALIAS).as_sql()
 }}}

 `DEFAULT_DB_ALIAS` is `default` and it hardcoded.

 Also `DEFAULT_DB_ALIAS` is used couple of times inside
 `django/db/models/sql/query.py` (please search by `DEFAULT_DB_ALIAS` in
 file to see details)

 It should use CURRENT_DB as other parts of Django
 Unfortunately I didn't check how migration determines current DB when
 `--database=...` is set so can't recommend exact solution, but I may see
 couple hints:

 1. DB may be get from `--database=...` directly (But not sure if that is a
 correct solution).
 2. DB may be get from
 [`DatabaseRouter`](https://docs.djangoproject.com/en/2.2/topics/db/multi-
 db/#database-routers) as other parts of Django (It is looking like correct
 solution)
 3. Here should be `using` option to be able set connection DB directly
 (for example, all functions inside `django/db/transaction.py` has `using`
 argument to be able set connection name directly)

 Right now I using workaround and set `from django.conf import settings;
 settings.DATABASES['default'] = current_db_taken_from_cmd` if command is
 `migrate`.
 Not all migrations fail. I don't know reason why it happens only with
 specific migrations, but I guess that it because this migration doing
 `CreateView`

 Migration file is looking like:

 {{{
 # Generated by Django 2.2.10 on 2021-10-06 04:17
 from dbview.helpers import CreateView

 import common.enums.some_enum
 from django.db import migrations, models
 import django.db.models.deletion


 class Migration(migrations.Migration):

     dependencies = [
         ('app_name', '0153_previous_migration'),
     ]

     operations = [
         migrations.CreateModel(
             name='SomeName',
             fields=[
                 ('id', models.AutoField(auto_created=True,
 primary_key=True, serialize=False, verbose_name='ID')),
                 ('create_datetime',
 models.DateTimeField(auto_now_add=True, verbose_name='A')),
                 ('user', models.CharField(default='admin', max_length=32,
 verbose_name='B')),
                 ('update_datetime', models.DateTimeField(auto_now=True,
 verbose_name='C')),
                 ...
             ],
             options={
                 'db_table': 'table_name',
                 'unique_together': {('other_table', 'table_name')},
             },
         ),
         CreateView(
             name='SomeNameView',
             fields=[
                 ('table_name_1',
 models.OneToOneField(on_delete=django.db.models.deletion.PROTECT,
 primary_key=True, serialize=False, to='orm_django.ApplyingInformation')),
                 ('table_name_2', models.IntegerField(verbose_name='A')),
                 ('table_name_3', models.IntegerField(verbose_name='B')),
                 ('table_name_3', models.IntegerField(verbose_name='C')),
                 ...
             ],
             options={
                 'db_table': 'table_view',
             },
         ),
         migrations.AddIndex(
             model_name='modelname',
             index=models.Index(fields=['field_A', 'field_B', ...],
 name='index_name'),
         ),
     ]
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/33280>
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/056.1b5ad189b40bd4936d0650527e5f5e10%40djangoproject.com.

Reply via email to