Changes between Initial Version and Version 2 of Ticket #33280


Ignore:
Timestamp:
Nov 11, 2021, 2:24:22 AM (3 years ago)
Author:
razielvamp666
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #33280

    • Property Resolutioninvalid
    • Property Status newclosed
    • Property Summary [bug] migration don't work with multiple databases (sometimes)Migration with django-database-view don't work with multiple databases.
  • Ticket #33280 – Description

    initial v2  
    1 My configuration is:
    2 
    3 
    4 {{{
    5 python 3.7.1
    6 }}}
    7 
    8 
    9 {{{
    10 Django==2.2.24
    11 django-axes==5.16.0
    12 django-bootstrap-modal-forms==1.3.1
    13 django-celery-results==1.0.4
    14 django-cors-headers==3.1.1
    15 django-database-view==0.3.0
    16 django-debug-toolbar==1.11
    17 django-dynamic-db-router==0.3.0
    18 django-ipware==3.0.7
    19 django-redis-cache==3.0.0
    20 django-redis-sessions==0.6.2
    21 django-ses==1.0.3
    22 django-storages==1.12.3
    23 django-taggit==0.24.0
    24 djangorestframework==3.12.4
    25 pytest-django==4.4.0
    26 }}}
    27 
    28 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 (`{}`).
    29 
    30 When I run `python manage.py migrate --database=some_db_name`
    31 
    32 I've get error:
    33 
    34 {{{
    35   Applying app_name.0154_migration_name...Traceback (most recent call last):
    36   File "manage.py", line 41, in <module>
    37     execute_from_command_line(sys.argv)
    38   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    39     utility.execute()
    40   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/core/management/__init__.py", line 375, in execute
    41     self.fetch_command(subcommand).run_from_argv(self.argv)
    42   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/core/management/base.py", line 323, in run_from_argv
    43     self.execute(*args, **cmd_options)
    44   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/core/management/base.py", line 364, in execute
    45     output = self.handle(*args, **options)
    46   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/core/management/base.py", line 83, in wrapped
    47     res = handle_func(*args, **kwargs)
    48   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/core/management/commands/migrate.py", line 234, in handle
    49     fake_initial=fake_initial,
    50   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/migrations/executor.py", line 117, in migrate
    51     state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
    52   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
    53     state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
    54   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/migrations/executor.py", line 245, in apply_migration
    55     state = migration.apply(state, schema_editor)
    56   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/migrations/migration.py", line 124, in apply
    57     operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
    58   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/dbview/helpers.py", line 21, in database_forwards
    59     self._create_standard_view(model, schema_editor)
    60   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/dbview/helpers.py", line 60, in _create_standard_view
    61     qs = str(model.view())
    62   File "/user/code/genki_labo/orm_django/models/novel_coronavirus_vaccine.py", line 136, in view
    63     return str(qs.query)
    64   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/models/sql/query.py", line 265, in __str__
    65     sql, params = self.sql_with_params()
    66   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/models/sql/query.py", line 273, in sql_with_params
    67     return self.get_compiler(DEFAULT_DB_ALIAS).as_sql()
    68   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 474, in as_sql
    69     extra_select, order_by, group_by = self.pre_sql_setup()
    70   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 54, in pre_sql_setup
    71     self.setup_query()
    72   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 45, in setup_query
    73     self.select, self.klass_info, self.annotation_col_map = self.get_select()
    74   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 254, in get_select
    75     sql, params = self.compile(col, select_format=True)
    76   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 405, in compile
    77     sql, params = node.as_sql(self, self.connection)
    78   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/models/expressions.py", line 737, in as_sql
    79     return "%s.%s" % (qn(self.alias), qn(self.target.column)), []
    80   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 396, in quote_name_unless_alias
    81     r = self.connection.ops.quote_name(name)
    82   File "/user/.pyenv/versions/gl/lib/python3.7/site-packages/django/db/backends/dummy/base.py", line 20, in complain
    83     raise ImproperlyConfigured("settings.DATABASES is improperly configured. "
    84 django.core.exceptions.ImproperlyConfigured: settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.
    85 }}}
    86 
    87 You can see that problem is here:
    88 
    89 {{{
    90 return self.get_compiler(DEFAULT_DB_ALIAS).as_sql()
    91 }}}
    92 
    93 `DEFAULT_DB_ALIAS` is `default` and it hardcoded.
    94 
    95 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)
    96 
    97 It should use CURRENT_DB as other parts of Django
    98 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:
    99 
    100 1. DB may be get from `--database=...` directly (But not sure if that is a correct solution).
    101 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)
    102 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)
    103 
    104 Right now I using workaround and set `from django.conf import settings; settings.DATABASES['default'] = current_db_taken_from_cmd` if command is `migrate`.
    105 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`
    106 
    107 Migration file is looking like:
    108 
    109 {{{
    110 # Generated by Django 2.2.10 on 2021-10-06 04:17
    111 from dbview.helpers import CreateView
    112 
    113 import common.enums.some_enum
    114 from django.db import migrations, models
    115 import django.db.models.deletion
    116 
    117 
    118 class Migration(migrations.Migration):
    119 
    120     dependencies = [
    121         ('app_name', '0153_previous_migration'),
    122     ]
    123 
    124     operations = [
    125         migrations.CreateModel(
    126             name='SomeName',
    127             fields=[
    128                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
    129                 ('create_datetime', models.DateTimeField(auto_now_add=True, verbose_name='A')),
    130                 ('user', models.CharField(default='admin', max_length=32, verbose_name='B')),
    131                 ('update_datetime', models.DateTimeField(auto_now=True, verbose_name='C')),
    132                 ...
    133             ],
    134             options={
    135                 'db_table': 'table_name',
    136                 'unique_together': {('other_table', 'table_name')},
    137             },
    138         ),
    139         CreateView(
    140             name='SomeNameView',
    141             fields=[
    142                 ('table_name_1', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, primary_key=True, serialize=False, to='orm_django.ApplyingInformation')),
    143                 ('table_name_2', models.IntegerField(verbose_name='A')),
    144                 ('table_name_3', models.IntegerField(verbose_name='B')),
    145                 ('table_name_3', models.IntegerField(verbose_name='C')),
    146                 ...
    147             ],
    148             options={
    149                 'db_table': 'table_view',
    150             },
    151         ),
    152         migrations.AddIndex(
    153             model_name='modelname',
    154             index=models.Index(fields=['field_A', 'field_B', ...], name='index_name'),
    155         ),
    156     ]
    157 }}}
Back to Top