Django South – Migrate From Python Code
Question:
Is it possible to run a migration from Python code? I don’t want to (actually I cannot) use the terminal command:
venv/bin/python src/manage.py migrate myapp
I need to run it from Python code as part of my business logic on a dynamically created database.
This is what I have so far:
db_name = uuid.uuid4()
from settings.local import DATABASES
new_database = {}
new_database['ENGINE'] = 'django.db.backends.mysql'
new_database['NAME'] = db_name
new_database['USER'] = DATABASES["default"]["USER"]
new_database['PASSWORD'] = DATABASES["default"]["PASSWORD"]
new_database['HOST'] = DATABASES["default"]["HOST"]
new_database['PORT'] = DATABASES["default"]["PORT"]
import settings
database_id = str(uuid.uuid4())
settings.DATABASES[database_id] = new_database
from django.core.management import call_command
call_command('migrate', 'catalogue', database=database_id)
But I get:
KeyError: '28a4eb10-91e4-4de8-8a74-15d72f8245ef'
Answers:
Yes, you can. Assuming it is called from within Django app:
from django.core.management import call_command
call_command('migrate', 'myapp')
I believe the issue you are having is that you are configuring the new database in runtime. So, the configuration you change in runtime is over the process/thread you are hitting with that code. The settings dict is immutable and you can not change it in runtime (see django docs).
I am not sure, but very probably the setting dict used by call_command is a copy from the original dict loaded from the settings configuration and that is why you get the key error (there is no new config in there).
By the way, is published that doing changes over settings configuration in runtime is not recommended by the django community.
Is it possible to run a migration from Python code? I don’t want to (actually I cannot) use the terminal command:
venv/bin/python src/manage.py migrate myapp
I need to run it from Python code as part of my business logic on a dynamically created database.
This is what I have so far:
db_name = uuid.uuid4()
from settings.local import DATABASES
new_database = {}
new_database['ENGINE'] = 'django.db.backends.mysql'
new_database['NAME'] = db_name
new_database['USER'] = DATABASES["default"]["USER"]
new_database['PASSWORD'] = DATABASES["default"]["PASSWORD"]
new_database['HOST'] = DATABASES["default"]["HOST"]
new_database['PORT'] = DATABASES["default"]["PORT"]
import settings
database_id = str(uuid.uuid4())
settings.DATABASES[database_id] = new_database
from django.core.management import call_command
call_command('migrate', 'catalogue', database=database_id)
But I get:
KeyError: '28a4eb10-91e4-4de8-8a74-15d72f8245ef'
Yes, you can. Assuming it is called from within Django app:
from django.core.management import call_command
call_command('migrate', 'myapp')
I believe the issue you are having is that you are configuring the new database in runtime. So, the configuration you change in runtime is over the process/thread you are hitting with that code. The settings dict is immutable and you can not change it in runtime (see django docs).
I am not sure, but very probably the setting dict used by call_command is a copy from the original dict loaded from the settings configuration and that is why you get the key error (there is no new config in there).
By the way, is published that doing changes over settings configuration in runtime is not recommended by the django community.