0

I'm using a django third party app called django-solo to give me a SingletonModel that I can use for some global project settings, since I don't need multiple objects to represent these settings.

This works great, but on a fresh database, I need to go in and create an instance of this model, or it won't show up in Django Admin.

How can I make django automatically make sure that when django is starting up, when it connects to the database, it creates this?

I tried using the following code that I got here in my settings_app/apps.py, but it doesn't seem to fire at any point:

from django.db.backends.signals import connection_created

def init_my_app(sender, connection, **kwargs):
   from .models import MyGlobalSettings

   # This creates an instance of MyGlobalSettings if it doesn't exist
   MyGlobalSettings.get_solo()

   print("Instance of MyGlobalSettings created...")

class SettingsAppConfig(AppConfig):
    ...
    def ready(self):
        connection_created.connect(init_my_app, sender=self)

The instance isn't created, and I don't see my print statement in the logs. Am I doing something wrong?

The sample code has something about using post_migrate as well, but I don't need any special code to run after a migration, so I'm not sure that I need that.

Update:

My INSTALLED_APPS looks like this:

INSTALLED_APPS = [
    ...
    'settings_app.apps.SettingsAppConfig',
    'solo',  # This is for django-solo
]

Also note that the ready() method does run. If I add a print statement to it, I do see it in the logs. It's just my init_my_app() function that doesn't run.

John
  • 2,551
  • 3
  • 30
  • 55
  • Please show us your `INSTALLED_APPS` setting. I suspect you need to look at [this answer](https://stackoverflow.com/a/37430196/3955830) for why your code isn't executing. – solarissmoke Jan 12 '20 at 05:57
  • @solarissmoke Question updated – John Jan 12 '20 at 06:01

1 Answers1

0

I think it's likely that the database connection is initialised before your app's ready() method runs - so attaching to the signal at that point is too late.

You don't need to attach to the signal there anyway - just do the check directly in the ready() method:

def ready(self):
    from .models import MyGlobalSettings
    MyGlobalSettings.get_solo()

Note that there is potential to run into other issues here - e.g., you will get an error if migrations for the MyGlobalSettings model haven't yet been applied on the database (when running manage.py migrate for the first time, for example) - you will probably need to catch specific database exceptions and skip the creation of this object in such cases.

solarissmoke
  • 30,039
  • 14
  • 71
  • 73