| | 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/app_name/app_name/models/file_name.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 | }}} |