読者です 読者をやめる 読者になる 読者になる

Django 1.7で追加されるAppConfigの紹介

この記事はDjango 1.7 alpha2の段階で書いています。
Django 1.7では、アプリケーションのロードや管理の仕組みが変更されます。
ドキュメントも追加されています。
Applications | Django documentation | Django

大雑把な説明

大雑把に説明すると、

  • アプリケーションのロード時にフックする仕組みが増えた(以前はmodels.pyやurls.pyなどにコードを書かないといけなかった)
  • アプリケーションにデフォルト設定を持たせて、差し替える仕組みが増えた(以前は各アプリケーションでsettingsを読めなければデフォルト値を使うような記述をしてた)
  • ロードされたアプリケーションのモジュールにアクセスする仕組みが増えた(以前はdjango.db.models.loading.AppCache.get_apps, ドキュメント無しのAPI)
  • ロードされたアプリケーションのモデルにアクセスする仕組みが増えた(以前はdjango.db.models.loading.AppCache.get_models, ドキュメント無しのAPI)

という感じです。
ロード時にフックポイントが増えたことで、runserverなどでアプリケーションを起動する前にアプリケーションの設定状態をチェックする仕組みも追加されています。
System check framework | Django documentation | Django

使い方

基本的な使い方はドキュメントに書かれているので、ここでは簡単な説明と補足など。
django.apps.AppConfigというクラスが追加されているので、これを継承したクラスを作成します。

django.contrib.adminのアプリの例

例えば、1.6以前はadmin.autodiscover()という、各アプリのadmin.pyモジュールをロードする関数呼び出しをurls.pyに書いてましたが、これはadminアプリのAppConfigのフックポイントに移動されました。
django/contrib/admin/apps.pyは次のとおり。

from django.apps import AppConfig
from django.core import checks
from django.contrib.admin.checks import check_admin_app
from django.utils.translation import ugettext_lazy as _


class SimpleAdminConfig(AppConfig):
    """Simple AppConfig which does not do automatic discovery."""

    name = 'django.contrib.admin'
    verbose_name = _("administration")

    def ready(self):
        checks.register('admin')(check_admin_app)


class AdminConfig(SimpleAdminConfig):
    """The default AppConfig for admin which does autodiscovery."""

    def ready(self):
        super(AdminConfig, self).ready()
        self.module.autodiscover()

readyメソッドではアプリケーションロード後に行う処理を記述します。例えば、autodiscoverやシステムチェック、シグナルの登録など。モデルにアクセスしたい場合はget_modelメソッドをここで使用します。

アプリケーションとモデルの取得

get_appsはアプリケーションモジュールのオブジェクトをリストで返します。get_models関数はロードされたモデルクラスをリストで返します。

>>> from django.apps import apps
>>> apps.get_apps()
[<module 'django.contrib.admin.models' from '/home/tokibito/.virtualenvs/django17-a2/local/lib/python2.7/site-packages/django/contrib/admin/models.pyc'>, <module 'django.contrib.auth.models' from '/home/tokibito/.virtualenvs/django17-a2/local/lib/python2.7/site-packages/django/contrib/auth/models.pyc'>, <module 'django.contrib.contenttypes.models' from '/home/tokibito/.virtualenvs/django17-a2/local/lib/python2.7/site-packages/django/contrib/contenttypes/models.pyc'>, <module 'django.contrib.sessions.models' from '/home/tokibito/.virtualenvs/django17-a2/local/lib/python2.7/site-packages/django/contrib/sessions/models.pyc'>, <module 'polls.models' from '/home/tokibito/sandbox/mysite/polls/models.pyc'>]
>>> apps.get_models()
[<class 'django.contrib.admin.models.LogEntry'>, <class 'django.contrib.auth.models.Permission'>, <class 'django.contrib.auth.models.Group'>, <class 'django.contrib.auth.models.User'>, <class 'django.contrib.contenttypes.models.ContentType'>, <class 'django.contrib.sessions.models.Session'>, <class 'polls.models.Question'>, <class 'polls.models.Choice'>]
INSTALLED_APPSでのAppConfig利用

INSTALLED_APPSは通常、アプリケーションのモジュールを文字列で指定しますが、Django 1.7ではAppConfigクラスも指定できます。
例えば、オリジナルのアプリケーションがpollsだとして、プロジェクトディレクトリにpolls_custom.pyというモジュールを以下の内容で追加します。

# coding: utf-8
from django.apps import AppConfig

class CustomAppConfig(AppConfig):
    name = 'polls'

settings.pyではpolls_custom.CustomAppConfigをINSTALLED_APPSに指定できます。

INSTALLED_APPS = (
    # ...
    'polls_custom.CustomAppConfig',
)

これで、pollsをINSTALLED_APPSに指定しなくてもpollsのモデルのモジュールなどがロードされます。
AppConfig.nameで指定したモジュールからモデルやadmin.pyなどがロードされることになります。
上記例では、オリジナルのアプリケーションにAppConfigクラスが無いですが、AppConfigが定義されているアプリケーションであれば、そのクラスを継承します。
アプリケーションでは、デフォルトのAppConfigを指定できます。
アプリケーションディレクトリの__init__.pyのdefault_app_config変数に、文字列でクラスを指定します。
django.contrib.adminだと以下のようになっています。

default_app_config = 'django.contrib.admin.apps.AdminConfig'

以上。