dynamically loading django apps at runtime dynamically loading django apps at runtime django django

dynamically loading django apps at runtime


Update for Django 1.8 on how to load an app that is not loaded yet

from collections import OrderedDictfrom django.apps import appsfrom django.conf import settingsfrom django.core import managementnew_app_name = "my_new_app"settings.INSTALLED_APPS += (new_app_name, )# To load the new app let's reset app_configs, the dictionary# with the configuration of loaded appsapps.app_configs = OrderedDict()# set ready to false so that populate will work apps.ready = False# re-initialize them all; is there a way to add just one without reloading them all?apps.populate(settings.INSTALLED_APPS)# now I can generate the migrations for the new appmanagement.call_command('makemigrations', new_app_name, interactive=False)# and migrate itmanagement.call_command('migrate', new_app_name, interactive=False)


With Django 2.2 this work for me

from collections import OrderedDictfrom django.apps import appsfrom django.conf import settingsfrom django.core import managementnew_app_name = "my_new_app"settings.INSTALLED_APPS += (new_app_name, )apps.app_configs = OrderedDict()apps.apps_ready = apps.models_ready = apps.loading = apps.ready = Falseapps.clear_cache()apps.populate(settings.INSTALLED_APPS)management.call_command('makemigrations', new_app_name, interactive=False)management.call_command('migrate', new_app_name, interactive=False)


To answer my own question...

While I do not have a completely general solution to this problem, I do have one that is sufficient for the purposes of dynamically loading apps during testing.

The basic solution is simple, and I found it at a wee little bixly blog.

Continuing with my example above, if I was in a django shell and wanted to add and load some new apps that were added to my apps directory, I could do

import osfrom django.conf import settingsfrom django.db.models import loadingfrom django.core import managementAPPS_DIR = '/path_to/apps/'for item in os.listdir(APPS_DIR):    if os.path.isdir(os.path.join(APPS_DIR, item)):        app_name = 'apps.%s' % item    if app_name not in settings.INSTALLED_APPS:        settings.INSTALLED_APPS += (app_name, )

and then

loading.cache.loaded = Falsemanagement.call_command('syncdb', interactive=False)