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 | | }}} |