app-engine-patchで静的ファイルを扱う 

はてなブックマーク - app-engine-patchで静的ファイルを扱う
Bookmark this on Delicious

app-engine-patch(以下AEP)を使ってDjango on GAEで開発を始めたわけですが、慣れないのでちょっとした事で詰まってばっかりで中々先に進みません。今日は静的ファイルの扱いで結構ハマったので記録しておきます。

やりたい事はmanage.py startappでアプリを作成した時に、アプリ内に作成されるmediaディレクトリに配置した静的ファイルを普通に配信したいという事です。

  + project
    - settings.py
    + myapp
      - urls.py
      - settings.py
      + media    # このディレクトリ以下のファイルを配信したい
        - logo.png
        - main.css
        - myfunc.js

最初に思いつくのは、myapp/urls.pyに静的ファイルへのパスを登録する方法ですが、Djangoのドキュメントによると、基本的に静的ファイルはDjangoでは扱わず、Webサーバで処理させると書いてあります。非効率で安全でないと書かれると流石にこのままでは駄目そうです。

かといって、app.yamlに静的ファイル用のディレクトリを登録するというのは、アプリ内で設定が閉じてないので、抵抗があります。(できるだけmyappの内容はmyappディレクトリ以下で行いたい)

さらに調べていると、AEPには静的ファイルを扱う為にmediautilsという仕組みが用意されていました。

このユーティリティを使うとそれぞれのアプリのmediaをproject直下の_generated_mediaにコピーしてくれます。またcssやjsファイルは1つのファイルにまとめて圧縮し容量を減らす効果もあります。作成された_generated_mediaをapp.yamlに登録しておけば、個々のアプリでの設定も最小限で済みます。またDjangoを介さずGAEの静的ファイルの配信機能を使えるので効率も良くて万事解決ですね。

使い方は以下になります。

  1. project/settings.pyのINSTALLED_APPSにmediautilsを追加

    INSTALLED_APPS = (
        'django.contrib.auth',
        'django.contrib.sessions',
        'django.contrib.admin',
        'appenginepatcher',
        'ragendja',
        'mediautils',  # これを追加
     
        'myapp',
    )
  2. myapp/settings.pyにmyapp/mediaにあるファイルの扱いを記述

    from ragendja.settings_post import settings
    settings.add_app_media('combined-%(LANGUAGE_CODE)s.js',
        'myapp/code.js',
    )
  3. manage.pyを利用してproject直下に_generatedを作成
    これでプロジェクト直下に_generated_mediaディレクトリが作成されます。内容を確認しましょう。

    ./manage.py generatemedia
  4. app.yamlに_generatedへのパスを通す

    - url: /media
      static_dir: _generated_media
      secure: optional
  5. テンプレート内からファイルにアクセスする
    テンプレート内で{{ MEDIA_URL }}アプリ名/ファイル名の様にアクセスします。例えば{{ MEDIA_URL }}myapp/logo.pngの様になります。

次に幾つか例外的な挙動があるので、それについて記述します。

  • プロジェクト直下のmediaディレクトリの扱い
    プロジェクト直下にmediaディレクトリを作成している場合は、そのディレクトリもgeneratemediaの処理対象になります。{{ MEDIA_URL}}global/ファイル名の様にアクセスできます。
  • cssとjsを纏めたくない
    cssやjsファイルは1つに纏めた方が効率等は良いと思うのですが、纏めたくない時もあると思います。僕は心理的な理由で纏めていません。myapp/settings.pyに以下の様に記述する事でcss及びjsをそのまま利用できます。

    from ragendja.settings_post import settings
    settings.add_uncombined_app_media('アプリ名')

これで漸くAEPで静的ファイルを扱えるようになりました。詳しくはAEPのサンプルに含まれているblueprintcssというアプリを見るのが良いと思います。

関連する記事

タグ: ,

コメントをどうぞ