Implement get_view_str approach.

A couple of other changes:

* AppRegistryNotReady fix (via both imports changes and docs update).
* Non-flat models structure support (app.models.submodels.Model).
* Minor refactoring.
This commit is contained in:
murchik
2020-11-19 13:42:29 +08:00
parent 4cb8a7a28a
commit 069e0a66b2
3 changed files with 70 additions and 47 deletions
-3
View File
@@ -1,3 +0,0 @@
# placeholder for git
from dbview.helpers import CreateView
from dbview.models import DbView
+48 -26
View File
@@ -1,42 +1,64 @@
import logging
from django.db import migrations
from django.apps import apps
class CreateView(migrations.CreateModel):
def database_forwards(self, app_label, schema_editor, from_state, to_state):
model = to_state.apps.get_model(app_label, self.name)
fake_model = to_state.apps.get_model(app_label, self.name)
if not self.allow_migrate_model(schema_editor.connection.alias, model):
if not self.allow_migrate_model(
schema_editor.connection.alias, fake_model):
raise
models = apps.get_app_config(app_label).models_module
model = getattr(models, self.name)
sql = 'DROP VIEW IF EXISTS %(table)s;'
model = self._get_model(fake_model, app_label, to_state)
args = {
'table' : schema_editor.quote_name(model._meta.db_table),
}
sql = sql % args
schema_editor.execute(sql, None)
sql = 'CREATE VIEW %(table)s AS %(definition)s'
self._drop_view(fake_model, schema_editor)
if hasattr(model, 'view'):
qs = str(model.view())
self._create_standard_view(model, schema_editor)
elif hasattr(model, 'get_view_str'):
self._create_view_from_raw_sql(model.get_view_str(), schema_editor)
else:
raise Exception('Your view needs to define either view or ' +
'get_view_str')
args['definition'] = qs
sql = sql % args
schema_editor.execute(sql, None)
raise Exception(f"{model} has neither view nor get_view_str")
def database_backwards(self, app_label, schema_editor, from_state, to):
model = from_state.apps.get_model(app_label, self.name)
sql = 'DROP VIEW IF EXISTS %s' % \
schema_editor.quote_name(model._meta.db_table)
fake_model = from_state.apps.get_model(app_label, self.name)
self._drop_view(fake_model, schema_editor)
def _get_model(self, state, app_label, fake_model):
models = apps.get_app_config(app_label).models_module
if hasattr(models, self.name):
return getattr(models, self.name)
# TODO: recursive search
for submodule in models.__dict__.values():
if hasattr(submodule, self.name):
return getattr(submodule, self.name)
logging.warning('Using fake model, this may fail with inherited views')
return fake_model
def _drop_view(self, model, schema_editor):
sql_template = 'DROP VIEW IF EXISTS %(table)s CASCADE'
args = {
'table': schema_editor.quote_name(model._meta.db_table),
}
sql = sql_template % args
schema_editor.execute(sql, None)
def _create_standard_view(self, model, schema_editor):
sql_template = 'CREATE VIEW %(table)s AS %(definition)s'
qs = str(model.view())
args = {
'table': schema_editor.quote_name(model._meta.db_table),
'definition': qs,
}
sql = sql_template % args
self._create_view_from_raw_sql(sql, schema_editor)
def _create_view_from_raw_sql(self, sql, schema_editor):
schema_editor.execute(sql, None)