Reputation:
I have a Django App I'm building, which we will call foo
.
Because of the way Foo is built, it requires a number of third-party django apps to function. For example, to run Foo
an install apps might look like:
INSTALLED_APPS = ('prereq1',prereq2','foo')
In fact, for Foo
to even be functional, 'prereq1', prereq2'
have to be installed in django. Now, I can add requirements to requirements.txt
or setup.py
to make sure the libraries are installed when someone goes to install Foo
, but I can't figure out if there is a way to have them installed in Django itself.
The reason for this is if someone wants to use Foo, I don't want to include instructions like:
In your
INSTALLED_APPS
addfoo
but also addscary_looking_library_name
andthing_you_dont_understand
.
So is it possible for an app in INSTALLED_APPS
to somehow require or inject further apps into that list?
Upvotes: 13
Views: 1996
Reputation: 5388
I agree with Daniel Roseman's answer about the system checks framework being an optimal place for these checks. The system checks framework was introduced Django 1.7.
However, assuming you have documentation, you can also document these prerequisites such as Django REST Framework did in their installation instructions.
You can then do something like the below in your code (django-mptt used as an example):
try:
from mptt.fields import TreeForeignKey
from mptt.models import MPTTModel
except ImportError:
raise ImportError(
'You are using the `foo` app which requires the `django-mptt` module.'
'Be sure to add `mptt` to your INSTALLED_APPS for `foo` to work properly.'
)
This is the method I have seen used in multiple applications. The onus of reading the documentation lies on the developer.
Perhaps this is an unwanted/unnecessary opinion, but the injection of dependencies into the INSTALLED_APPS
is nothing that I feel you should be handling with your application.
I typically try to follow the Zen of Python when designing applications:
INSTALLED_APPS
INSTALLED_APPS
is hard to explain. If the third-party dependencies are complicated, let the developer decide.INSTALLED_APPS
.INSTALLED_APPS
- which is why there is no obvious way to do what you want (injection).If a developer wants to activate an app, they will. As you so eloquently stated in your example, scary_looking_library_name
and thing_you_dont_understand
is the responsibility of the developer to understand. Choosing to install it for developer is imposing an unnecessary security risk. Let the developer choose to use your application and initialize its dependencies.
Upvotes: 18
Reputation: 1959
I prefer to do dependency check, however i think you demand the below code to inject your desired apps into the django site.
you must put it somewhere to execute, and do a check not to re-execute when the dependencies are loaded.
also if you use it, the 'someapp' in settings.INSTALLED_APPS
will not work correctly. maybe you need to also alter it.
from django.apps import apps
installed_apps = [app.__name__ for app in apps.get_apps()]
new_installed_app = installed_app + ['your desired app1', 'your desired app2', ...]
apps.set_installed_apps(new_installed_apps)
Upvotes: 2
Reputation: 599450
I think the system check framework would be a good place for this. You can write a check that verifies the presence of those apps in the settings and raises an error if they are not there.
Upvotes: 6