How to configure django standalone app to install automatically all sub apps? - python

Problem description
I have django standalone app named django_codeserver. It can be loaded from my private package registry as a pip-package.
My app contains about twenty sub-apps for example django_codeserver.headers, django_codeserver.genders etc.
Current behaviour
To register all models in my project which uses django_codeserver, I have to register all the sub applications in the parent project INSTALLED_APPS such as:
INSTALLED_APPS = [
...
'django_codeserver.headers',
'django_codeserver.genders'
...
]
Preferred behaviour
I would want all the sub apps being registred in the parent project when I only:
Install the standalone django app as pip-package (pip install django-codeserver)
Register only the parent app in parent project installed apps:
INSTALLED_APPS = [
'django_codeserver
]

After researching this problem, I couldn't find the exact solution. However we can kind of deal with this problem as pointed out here.
So we are not able to automatically install sub apps, but instead we can reuse application with all sub apps included without directly write all apps in the parent project INSTALLED_APPS.
In that way reusable app installation documentation not changing after adding a new sub app. Also the maintenance of included sub apps is moved from reusable app consumer to its provider.

Related

When creating a package, how do I manage migrations of a weak dependency?

I have a Django app that I would like to package and offer the community through PyPI repository. Its only strong dependance is Django. It also integrates nicely with Django CMS and offers additional integration for Django CMS. I plan to offer this additional functionality only to projects with Django CMS installed. (This is what I call a weak dependency - will install and work without it, but work even bitter with it.) Specifically, some models are only defined if the base model CMSPlugin from Django CMS is installed.
Is there a good/right way to manage migrations, though?
I cannot include migrations of models depending on CMSPlugin in the package since users w/o a Django CMS installations will not be able to run it.
If I omit the migrations depending on CMSPlugin users with Django CMS will create them on first installation. I fear, however, that on every update of the package those migrations will be lost on pip install upgrade when the package is overwritten.
Since these models are not necessarily used in your package it is best to have them in another Django app, which can be a sub-app of your app or perhaps just one of the apps present in your package. If a user has installed CMSPlugin then they can now simply add this extra app of yours to the INSTALLED_APPS list to use it, this also comes with the benefit that your users now have the choice to use it or not.
This way you can also easily adapt your views if this app is installed or not by using the app registries is_installed method [Django docs]:
from django.apps import apps
def some_view(request):
if apps.is_installed('yourpackage.path.to.weak_dependency_subapp'):
# Weak dependency is present
else:
# Weak dependency is absent
Note: You would have to be careful though that you don't import this apps models if it is not installed, otherwise it may give you some error since it would not be loaded.
Edit: To make the sub-app you can either do as you did by cd'ing to the apps directory and python ../manage.py startapp subappname or directly python manage.py startapp subappname <your_app>/subappname (The directory subappname needs to be made first) and then setting it's app config's name attribute to <your_app>.subappname.

Two ways of including an app in INSTALLED_APPS

Say I have an app called polls.
What is the difference between including an app in INSTALLED_APPS like this 'polls.apps.PollsConfig' and just specifying the app's name ( 'polls')?
The official Django tutorial recommends the former.
The latter is the old way and it has got problems in some cases with the position in INSTALLED_APPS as the preferred way has been to put your apps the last, so all your dependencies are already available when your app is loaded.
The former is the new improved way when you load your app configuration instance first and so all the dependencies are aware of your app and also your app prior to loading has got all the dependencies available.
You should use AppConfig and put it at the top of the list, plain app positioned last is relict of the past.

User to user messaging with django-postman

I'm new using django-postman and django and I just downloaded a copy of the django-postman package to use with my app. I added 'postman' to the INSTALLED_APPS settings.py of my project and url(r'^messages/',include('postman.urls',namespace='postman',app_name='postman')), in urls.py. However, I'm not sure where to put the downloaded package and integrated with my project. I think I added the app to my Python path with pip install django-postman==3.6.2, but when I use url(r'^messages/',include('postman.urls',namespace='postman',app_name='postman')) my django program says that there's not an app called 'postman'. How do I include the django-postman app to my project? Also since the app_name='postman' in urls.py is not longer valid for python 3.6 should I just take it out of the statment?

Django add management command without installing as app

I've created a package for use with django, the main feature of which is accessible through a management command. However, in order to make management commands accessible, django seems to insist on the package being listed as an app in INSTALLED_APPS in settings.py.
This application is merely used as part of our build process while doing intergration testing. It does not even need to be installed on developer machines, let alone end up in our production environment. However, since it needs to be in settings.py's installed apps, it also spreads to requirements.txt, as it suddenly breaks builds wherever it is not installed.
Is there a way to inject a management command without the package being installed as a full-blown app?
Alternatively: is there a standard/recommended way to make a command available to tox in a different way than through a management command?
One solution is to have a separate settings.py for the build process that adds the app containing this command to INSTALLED_APPS. Then you can run manage.py mycommand --settings=build_settings or whatever.
The settings file itself can be as simple as:
from main_settings import *
INSTALLED_APPS += ['myapp']

Adding several apps to INSTALLED_APPS at once

I am working on an app, which requires another app to be installed. I can add it to my setup.py and it will install the other app too.
After installing my application, i need to add it to INSTALLED_APPS, but i need to add the external app too.
Is there a way to pass the other application implicitly?
What's the recommended way to handle that kind of dependency to avoid asking the users to add more than one app when it is required?
Without doing some strange hacking, there's no way to do this, nor should there be. The user should be aware of what they are adding to their project and what dependancies are required. Remember Django's design philosophy:
Explicit is better than implicit
Have a look at some of the following apps. They all require dependancies in the INSTALLED_APPS. They make it clear in the docs that the user has to add them to their project manually:
Django Zinnia
Django Admin2
Django Filer
Django Filebrowser
There is a library called django-autoconfig that lets you do this. You basically include an autoconfig.py in your app, and if your app is include in INSTALLED_APPS, it's autoconfig.py is loaded.
The file should look something like this:
SETTINGS = {
'INSTALLED_APPS': [
'external_app_1',
'external_app_2',
],
}
Read the docs for more information about ordering and more advanced stuff like that.

Categories

Resources