1
|
# this file derive from django-tenant-schemas
|
2
|
# Author: Bernardo Pires Carneiro
|
3
|
# Email: carneiro.be@gmail.com
|
4
|
# License: MIT license
|
5
|
# Home-page: http://github.com/bcarneiro/django-tenant-schemas
|
6
|
import django
|
7
|
|
8
|
if django.VERSION < (1, 7, 0):
|
9
|
from django.conf import settings
|
10
|
from django.db import connection
|
11
|
from south import migration
|
12
|
from south.migration.base import Migrations
|
13
|
from entrouvert.djommon.multitenant.middleware import TenantMiddleware
|
14
|
from entrouvert.djommon.management.commands.safemigrate import Command as SafeMigrateCommand
|
15
|
from entrouvert.djommon.multitenant.management.commands.sync_schemas import Command as MTSyncCommand
|
16
|
from entrouvert.djommon.multitenant.management.commands.migrate_schemas import Command as MTMigrateCommand
|
17
|
from entrouvert.djommon.multitenant.management.commands import SyncCommon
|
18
|
|
19
|
|
20
|
class SafeMigrateCommand(SyncCommon):
|
21
|
help = "Safely migrate schemas with South"
|
22
|
option_list = MTMigrateCommand.option_list
|
23
|
|
24
|
def handle(self, *args, **options):
|
25
|
super(Command, self).handle(*args, **options)
|
26
|
|
27
|
MTSyncCommand().execute(*args, **options)
|
28
|
connection.set_schema_to_public()
|
29
|
if self.sync_public:
|
30
|
self.fake_public_apps()
|
31
|
if self.sync_tenant:
|
32
|
self.fake_tenant_apps(self.domain)
|
33
|
connection.set_schema_to_public()
|
34
|
MTMigrateCommand().execute(*args, **options)
|
35
|
|
36
|
def _set_managed_apps(self, included_apps, excluded_apps):
|
37
|
""" while sync_schemas works by setting which apps are managed, on south we set which apps should be ignored """
|
38
|
ignored_apps = []
|
39
|
if excluded_apps:
|
40
|
for item in excluded_apps:
|
41
|
if item not in included_apps:
|
42
|
ignored_apps.append(item)
|
43
|
|
44
|
for app in ignored_apps:
|
45
|
app_label = app.split('.')[-1]
|
46
|
settings.SOUTH_MIGRATION_MODULES[app_label] = 'ignore'
|
47
|
|
48
|
def _save_south_settings(self):
|
49
|
self._old_south_modules = None
|
50
|
if hasattr(settings, "SOUTH_MIGRATION_MODULES") and settings.SOUTH_MIGRATION_MODULES is not None:
|
51
|
self._old_south_modules = settings.SOUTH_MIGRATION_MODULES.copy()
|
52
|
else:
|
53
|
settings.SOUTH_MIGRATION_MODULES = dict()
|
54
|
|
55
|
def _restore_south_settings(self):
|
56
|
settings.SOUTH_MIGRATION_MODULES = self._old_south_modules
|
57
|
|
58
|
def _clear_south_cache(self):
|
59
|
for mig in list(migration.all_migrations()):
|
60
|
delattr(mig._application, "migrations")
|
61
|
Migrations._clear_cache()
|
62
|
|
63
|
def _fake_schema(self, tenant):
|
64
|
connection.set_tenant(tenant, include_public=False)
|
65
|
SafeMigrateCommand().fake_if_needed()
|
66
|
|
67
|
def fake_tenant_apps(self, schema_name=None):
|
68
|
self._save_south_settings()
|
69
|
|
70
|
apps = self.tenant_apps or self.installed_apps
|
71
|
self._set_managed_apps(included_apps=apps, excluded_apps=self.shared_apps)
|
72
|
|
73
|
if schema_name:
|
74
|
self._notice("=== Running fake_if_needed for schema: %s" % schema_name)
|
75
|
connection.set_schema_to_public()
|
76
|
tenant = TenantMiddleware.get_tenant_by_hostname(schema_name)
|
77
|
self._fake_schema(tenant)
|
78
|
else:
|
79
|
all_tenants = TenantMiddleware.get_tenants()
|
80
|
if not all_tenants:
|
81
|
self._notice("No tenants found")
|
82
|
|
83
|
for tenant in all_tenants:
|
84
|
Migrations._dependencies_done = False # very important, the dependencies need to be purged from cache
|
85
|
self._notice("=== Running fake_if_needed for schema %s" % tenant.schema_name)
|
86
|
self._fake_schema(tenant)
|
87
|
|
88
|
self._restore_south_settings()
|
89
|
|
90
|
def fake_public_apps(self):
|
91
|
self._save_south_settings()
|
92
|
|
93
|
apps = self.shared_apps or self.installed_apps
|
94
|
self._set_managed_apps(included_apps=apps, excluded_apps=self.tenant_apps)
|
95
|
|
96
|
self._notice("=== Running fake_if_needed for schema public")
|
97
|
SafeMigrateCommand().fake_if_needed()
|
98
|
|
99
|
self._clear_south_cache()
|
100
|
self._restore_south_settings()
|
101
|
|
102
|
if django.VERSION < (1, 7, 0):
|
103
|
Command = SafeMigrateCommand
|
104
|
else:
|
105
|
raise RuntimeError('Django 1.7: please use migrate_schemas')
|