Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
122 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
from __future__ import unicode_literals | ||
|
||
from django.apps import apps | ||
from django.db.backends.utils import truncate_name | ||
from django.db.migrations import operations | ||
from django.db.migrations.operations.base import Operation | ||
from django.utils.six import iteritems | ||
|
||
from .models import Managed, db_schema_table | ||
|
||
|
||
class TenantModelOperation(Operation): | ||
def get_tenant_model(self, app_label, from_state, to_state): | ||
raise NotImplementedError | ||
|
||
def create_tenant_project_state(self, tenant, state, connection): | ||
managed = Managed("%s.%s" % (tenant._meta.app_label, tenant._meta.object_name)) | ||
project_state = state.clone() | ||
for key, model_state in iteritems(project_state.models): | ||
options = model_state.options | ||
if options.get('managed') == managed: | ||
db_table = options.get('db_table') | ||
if not db_table: | ||
db_table = truncate_name("%s_%s" % key, connection.ops.max_name_length()) | ||
options.update( | ||
managed=True, | ||
db_table=db_schema_table(tenant, db_table), | ||
) | ||
return project_state | ||
|
||
def tenant_operation(self, tenant_model, operation, app_label, schema_editor, from_state, to_state): | ||
connection = schema_editor.connection | ||
for tenant in tenant_model._base_manager.all(): | ||
tenant_from_state = self.create_tenant_project_state(tenant, from_state, connection) | ||
tenant_to_state = self.create_tenant_project_state(tenant, to_state, connection) | ||
operation(app_label, schema_editor, tenant_from_state, tenant_to_state) | ||
|
||
def database_forwards(self, app_label, schema_editor, from_state, to_state): | ||
tenant_model = self.get_tenant_model(app_label, from_state, to_state) | ||
operation = super(TenantModelOperation, self).database_forwards | ||
self.tenant_operation(tenant_model, operation, app_label, schema_editor, from_state, to_state) | ||
|
||
def database_backwards(self, app_label, schema_editor, from_state, to_state): | ||
tenant_model = self.get_tenant_model(app_label, to_state, from_state) | ||
operation = super(TenantModelOperation, self).database_backwards | ||
self.tenant_operation(tenant_model, operation, app_label, schema_editor, from_state, to_state) | ||
|
||
|
||
class CreateTenantModel(TenantModelOperation, operations.CreateModel): | ||
def get_tenant_model(self, app_label, from_state, to_state): | ||
model_state = to_state.models[app_label, self.name_lower] | ||
managed = model_state.options.get('managed') | ||
return apps.get_model(managed.tenant_model) | ||
|
||
|
||
class DeleteTenantModel(TenantModelOperation, operations.DeleteModel): | ||
def get_tenant_model(self, app_label, from_state, to_state): | ||
model_state = from_state.models[app_label, self.name_lower] | ||
managed = model_state.options.get('managed') | ||
return apps.get_model(managed.tenant_model) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from __future__ import unicode_literals | ||
|
||
from django.core.management import call_command | ||
from django.test.utils import captured_stdout, override_settings | ||
|
||
from .utils import TenancyTestCase | ||
|
||
|
||
@override_settings(MIGRATION_MODULES={'tests': 'tests.test_operations_migrations'}) | ||
class TestTenantSchemaOperations(TenancyTestCase): | ||
def test_migrate_forwards(self): | ||
with captured_stdout() as stdout: | ||
call_command('migrate', 'tests', interactive=False, stdout=stdout) | ||
with captured_stdout() as stdout: | ||
call_command('migrate', 'tests', 'zero', interactive=False, stdout=stdout) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# -*- coding: utf-8 -*- | ||
from __future__ import unicode_literals | ||
|
||
from django.db import migrations, models | ||
|
||
from tenancy.models import Managed | ||
from tenancy.operations import CreateTenantModel, DeleteTenantModel | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
operations = [ | ||
CreateTenantModel( | ||
name='BaseDefinition', | ||
fields=[ | ||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), | ||
], | ||
bases=(models.Model,), | ||
options={ | ||
'managed': Managed('tenancy.Tenant'), | ||
} | ||
), | ||
DeleteTenantModel(name='BaseDefinition'), | ||
] |
Empty file.