Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we use apps.py for application-level configuration as a contrast to settings.py for project-level configurations?

Tags:

python

django

This question has been asked earlier: What is the purpose of apps.py in Django 1.9?

Application configuration objects store metadata for an application. Some attributes can be configured in AppConfig subclasses. Others are set by Django and read-only.

However, what does it mean by metadata for application? Is it limited only to those AppConfig metadata:name, verbose_name, path, label, module, models_module?

Or does it make sense to extends beyonds the predefined metadata, especially for Application Specific metadata, for example in blog apps we have a date format configuration, usually defined as follows:

# File: settings.py
BLOG = {
    'DATE_FORMAT': 'ddMMYYY',
}

At which it is being used as follow:

# File: blog/<...>.py
from django.conf import settings
date_format = settings.BLOG['DATE_FORMAT']

On contrary, we could move this configuration into blog/apps.py as BlogConfig?

class BlogConfig(AppConfig):
    name = 'blog'
    verbose_name = 'Awesome Blog'
    date_format = 'ddMMYYYY'

So that throughout the code in the application, date_format is being used by:

# File: blog/<...>.py
from django.apps import apps
date_format = apps.get_app_config('blog').date_format

It sounds to me that settings.py is project settings, but not an application settings. Thus it is more sounds to put all application settings inside apps.py then settings.py. So, is this a valid assumption/argument/convention for me to put application configuration inside apps.py instead of settings.py?

like image 221
Yeo Avatar asked Jun 28 '16 11:06

Yeo


1 Answers

A project is unique per django installation, while an app is supposed to be reusable.

If you put custom app settings in your project's settings.py they are supposed to be modifiable, especially if you (or others) reuse this app for another project.

Now, if you put these custom settings in your app's apps.py, this means they won't be modifiable on a per project basis. In which case there is no reason to put them in apps.py rather than in a constants submodule for instance. Unless you want to provide a limited set of possible configs:

class BlogConfig(AppConfig):
    name = 'blog'
    verbose_name = "Blog"
    date_format = 'ddMMYYYY'


class CustomizableDateFormatBlogConfig(BlogConfig):
    date_format = getattr(settings, 'BLOG_DATE_FORMAT', BlogConfig.date_format)


class I18nBlogConfig(BlogConfig)
    verbose_name = _("Blog")

The default_app_config would be BlogConfig but the project using the app would be able to choose CustomizableDateFormatBlogConfig or I18nBlogConfig as well.

However this makes very poorly customizable apps. In the example above, if you want to let the app users use both CustomizableDateFormatBlogConfig and I18nBlogConfig, you would need to do something like this:

class BlogConfig(AppConfig):
    name = 'blog'
    verbose_name = "Blog"
    date_format = 'ddMMYYYY'


class CustomizableDateFormatMixin:
    date_format = getattr(settings, 'BLOG_DATE_FORMAT', BlogConfig.date_format)


class I18nMixin:
    verbose_name = _("Blog")


class CustomizableDateFormatBlogConfig(CustomizableDateFormatMixin, BlogConfig):
    pass


class I18nBlogConfig(I18nMixin, BlogConfig):
    pass


class I18nCustomizableDateFormatBlogConfig(I18nMixin, CustomizableDateFormatMixin, BlogConfig):
    pass

So, apart specific cases where you need to provide a set of few different app configs, you'd better put your custom app settings in the project's settings.py.

like image 176
Antoine Pinsard Avatar answered Oct 21 '22 05:10

Antoine Pinsard