[Solved]-Does Django's singleton architecture make it unworkable as a standalone ORM in a library?

2đź‘Ť

You can check if django has already been configured.

from django.apps import apps
from django.conf import settings

if not apps.ready:
    settings.configure()
    django.setup()

When starting Django application – core python library can be configured as separate app an be loaded on startup.

Also, check this answer on dynamic app loading at runtime.

👤Oleg Russkin

2đź‘Ť

A simple answer is how to initialize Django in a standalone application and do it compatible with Django applications.

import os
import django

if not 'DJANGO_SETTINGS_MODULE' in os.environ:
    os.environ['DJANGO_SETTINGS_MODULE'] = 'mysettings'

    # # or without DJANGO_SETTINGS_MODULE directly
    # from django.conf import settings
    # settings.configure(DATABASES=... other...)

    django.setup()

# this shouldn't be before DJANGO_SETTINGS_MODULE or settings.configure(...)
from myapp.models import MyModel
# this shouldn't be called before django.setup()
queryset = MyModel.objects.filter(...)

This is more compatible with Django then the answer by Oleg Russkin (where a risk of cyclic dependency at django.setup() is possible if the code is called inside inside a setup() initiated by another similar code or a normal Django project started by manage. It is similar to manage.py where django.setup() is also called internally by execute_from_command_line(sys.argv). The setup initializes all modules related to INSTALLED_APPS all urls modules and consequently all views etc. Many of them are lazy, but still. If any code called by setup() depends on this then neither the condition not apps.ready doesn’t help. The setup() is not reentrant and the startup fails.)


Much more general answer

An important concept of Django is to support writing reusable parts of code (“applications” in Django terminology, that can be developed and tested independently. There can be also a tree of dependencies, but uncontrolled mutual dependencies should be avoided if possible) Reusable applications are expected that they can be easier combined to whole project (“project” in Django terminology is with all settings necessary to run it by Python.)

The only unavoidable and useful “singleton” in Django ORM are database connections django.db.connections and django.conf.settings especially INSTALLED_APPS. Only one connection should be used to the same database from the same process or thread.

Django is very configurable. An extreme example: It is possible to write a single file project where all code like settings, models, URL configs and views is defined in one file. That extreme that is probably useful only for some special tests or very short demos or as an exercise. It is even possible to define a project by one file with two “reusable” applications 🙂

Django supports also “legacy databases” where the database structure is shared with existing non Django applications and models can be created by inspectdb command. Table names in such models are explicit and don’t contain the app name. On the other hand the app name prefix is useful to prevent a possible conflict of the same table names from independent “applications”. An important decision is if you can use it as a “legacy” database or a normal Django database.

You can decide between following two solutions or to combine them:

  • Use e.g. foo_models or bar.models and import all models from them e.g. to app.models and add only that "app" to INSTALLED_APPLICATIONS. This can be viable if it is only for one company and never otherwise and central name assigment is possible. (easiest but little naive)
  • Use some coarse separation of namespaces to several apps. You should probably use not more than one app with simple names without app name prefix.

Think ahead about migrations**. They will be probably very complicated and very soon impossible if you will create later more projects for the same database and different subsets of database tables without separating them to more apps and without app namespace.

There is really no “singleton” in Django ORM except of django.db.connections itself. If you use more databases you can direct some tables to a specific database by DATABASE_ROUTERS, even with two different models that use the same table name without a prefix.

👤hynekcer

Leave a comment