PinaxでDjango入門2 basic_projectのprofilesを変更 djangoの名前空間

January 18, 2009 at 11:01 PM | View Comments

ハンズオンの課題その1

pinaxのbasic_projectのprofileをcomplete_projectのprofileに変更する

をやってみたいと思います。

以下動画、

http://www.ueblog.org/media/static/django6_1/d21.swf

http://www.ueblog.org/media/static/django6_1/d22.swf

http://www.ueblog.org/media/static/django6_1/d23.swf

今回はYouTubeにもアップしてみました。

動画を見てもらえば分かると思いますが、数々のエラーメッセージから判断して

  • settings.py のROOT_URLCONFの確認
  • settings.py のINSTALL_APPSに足りないアプリを設定する
  • 名前空間から外れているアプリをコピーする
  • テンプレートタグurl({% url hogehoge %})のnameの逆引きエラーを見つける
  • templatesを置く場所の確認

などを行っています。

いろいろやってますが基本的にはどれも「Djangoプロジェクトの名前空間」の問題になります。

今回の例ではpinaxの外部から何か別のソースを用意したり、新しいコードを書いたわけでもないのですが、

complete_projectからは見えたappやtemplateがbasic_projectからは見えないという事例がいくつもありました。

この差がちゃんと理解できるようになればDjangoのプロジェクトで、どこになにを置いたらいいのか?または、置いてあるappやtemplateを使うためにはどうしたらいいのかが分かるようになると思います。

また、pinaxは通常の「django-admin.py startproject」で作ったプロジェクトでは見えない位置に置いたアプリやライブラリを読み込んでいます。

manage.pyを拡張しているのですが、その意味が分かれば

  • レンタルサーバーなどで通常のsite-packagesなど置きたい場所にモジュールを置けない場合の対処
  • 複数のProjectで共有しているDjangoのアプリの置き方

などが分かるようになると思います。

では、順番に見ていきましょう。

まず、前回動かしたpinax/projects/basic_projectをpinax/project/basic_project_2という名前でコピーして、syncdb&runserveをします。

% cd pinax/projects
% cp -r basic_project basic_project_2
% cd basic_project_2
% python manage.py syncdb
% python manage.py runserver 0.0.0.0:8001

しかし、ここではエラーが発生します。

No module named basic_project.url

これは、basic_project/urls.pyを探したけど見つからなかったというエラーです。なぜなら、いま動かしているのはbasic_project_2なので、basic_projectは現在のプロジェクトの名前空間にはないわけです。

動かすべきurls.pyは basic_project_2/urls.pyなので、それをDjangoに教えなくはいけません。具体的にはsettings.pyの

ROOT_URLCONF = 'basic_project_2.urls'

と設定してあげればOKです。

Djangoはsettings.pyの置いてあるプロジェクトは見えても、その隣にあるプロジェクトは見えないことがポイントです。

さて、このROOT_URLCONFは何かというと、ブラウザ等でアクセスがきたときのURLによって、それぞれ違う画面を表示するのがWEBアプリなのですが、その振り分けをするモジュールを設定しています。

実際にurls.pyがどのようになっているかというと

urlpatterns = patterns('',
    url(r'^$', direct_to_template, {"template": "homepage.html"}, name="home"),

    (r'^about/', include('about.urls')),
    (r'^account/', include('account.urls')),
    (r'^openid/(.*)', PinaxConsumer()),
    (r'^profiles/', include('basic_profiles.urls')),
    (r'^notices/', include('notification.urls')),
    (r'^announcements/', include('announcements.urls')),

    (r'^admin/(.*)', admin.site.root),
)

というようになっていて、

たとえば http://wwww.hoge.org/ がルートだとして

http://www.hoge.org/ だったらdirect_to_templateという関数に渡します。

渡される関数はviews関数と呼ばれ、リクエスト情報を元に実際の表示を担当する関数です。

includeというのは引数の別のurls.pyを展開して、そのあとの処理を任せるようになっています。

この辺りを全部説明すると長くなるので割愛しますが、ROOT_URLCONFに指定されたurls.pyはURLを振り分けて、実際に表示する関数(veiws関数)を呼び出すと理解しておいてください。

settings.pyとurls.pyのbasic_profilesを profilesに変更したあと、プロジェクトを動かすと

photos アプリをはじめ

  • photos (projects/complete_project/appsの下)
  • photolouge (apps/external_appsの下)
  • app_plugins (apps/external_appsの下)
  • friends (apps/external_appsの下
  • microblogging (apps/local_appsの下)
  • tribes (apps/local_appsの下)
  • avatar (apps/external_appsの下)
  • friends_app (projects/complete_project/appsの下)

と、様々なappが無いというエラーが発生します。

話すより書いた方がいいと思ったので動画ではしゃべってませんが

basic_project_2直下にないし、adminのようにdjango自体のアプリでないアプリがなぜ使うことができるか?ということが重要です。

pinaxで使われているmanage.pyはdjango-admin.py startprojectで生成されるmange.pyを拡張していて、

拡張している部分は

path = addsitedir(join(settings.PINAX_ROOT, "libs/external_libs"), set())
if path:
    sys.path = list(path) + sys.path
sys.path.insert(0, join(settings.PINAX_ROOT, "apps/external_apps"))
sys.path.insert(0, join(settings.PINAX_ROOT, "apps/local_apps"))
sys.path.insert(0, join(settings.PROJECT_ROOT, "apps"))

のようになっています。

manage.pyを動かすときに、pinax/apps/external_apps, pinax/apps/local_appsと、そのプロジェクト直下のappsにPATHを通していて

(あと、pinax/libs/external_libs直下のライブラリにもPATHを通しています)

こうすることによって、複数のprojectで使いまわすappへのPATHを通すことを実現しているのです。

mange.pyを使えるのは開発時のみですが、各projectにはdeployというディレクトリがあって、mod_python, mod_wsgi, fastcgiで動かす場合のヒントがあるので本番時でも、それらを使うことで運用ができます。

これらはレンタルサーバーで活用するときにライブラリのインストールが通常のsite-packagesにできない場合など参考にするといいかもしれません。

ここではphotosとfriends_appはcomplete_project/appsの下にあり、名前空間から外れているのでbasic_projects_2/appsへコピーをしています。

さて、次は TemplateDoesNotExistのエラーです。

djangoはappの下にtemplatesというディレクトリがあれば、なにも設定しなくてもそこからtemplateファイルを探すのですがsettings.pyのTEMPLATE_DIRSに設定すればそちらを優先して探します。

pinaxのプロジェクトはプロジェクト直下のtemplatesを割り当てていたのですが、今回のprofilesとfriends_appに関してはcomplte_project/templatesの下にしかなく、どちらの下にもなかったので、

% cp -r complete_project/templates/profiles basic_projects_2/templates/profiles
% cp -r complete_project/templates/friends_app basic_projects_2/templates/friends_app

でコピーしました。

さて、最後のエラーはtemplate tagです。

Caught an exception while rendering: Reverse for 'basic_project_2.avatar_change' with arguments '()' and keyword arguments '{}' not found.

のようなエラーがでて、下の方に

<a href="{% url avatar_change %}"

の部分が赤くなっていたと思うのですが、

この {% url hogehoge %}はテンプレートタグと呼ばれるもので、中でもurlというのは、urls.pyの中で

(r'^about/', include('about.urls')),

のようなタプルではなく

url('^change/$', 'change', name='avatar_change'),

のようなurl関数を使って設定したもののなかから nameで指定されたURLを探し出すものです。

この場合は{% url avatar_change %}を http://localhost:8001/avatar/change/と置き換えます。

こうしておけば /change ではなく、別のURLに変更したいときに該当するurls.py一箇所を変えればテンプレートの変更をする必要がないので便利です。

しかも、今回のようにhttp://localhost::8001/avatar/changeをurls.pyに設定し忘れたときにエラーが発生するのも良いところです。

実際に変更するのはcomplete_project/urls.pyと同じように、basic_project_2/urls.pyに

(r'^tweet/', include('microblogging.urls')),
(r'^avatar/', include('avatar.urls')),

を追加すれば大丈夫です。

これで、profilesが一応complete_projectと同じような画面がでたと思います。

次はmicrobloggingの導入の予定です。

ただ、他のフレームワークや言語をやっている人がDjangoをちょっと触ってみたいという意図では

今回のハンズオンの課題は難しすぎたかもしれないので、もっと簡単なDjangoの基本を一回間に入れようかと思います。

categories: django-handson6, django
Read and Post Comments

PinaxでDjango入門1 complete_projectとbasic_projectを動かす

January 17, 2009 at 12:02 AM | View Comments

先日のDjango勉強会Disc.6のフォローアップ第1回です。

  • Python2.5
  • django1.0
  • PIL
  • pinax (svnのtrunk)

で行っています。

まずpinaxのインストールは

% svn checkout https://svn.pinaxproject.com/pinax/trunk/ pinax

でsubversionを使ってインストールしてください。

そして問題のPILのが必要なのですが、インストールは前回のエントリーを参考にしてください。

ueBLOG | Python Image Libraryのインストール

まず、今回はcomplete_projectとbasic_projectを動かすところまでやってみたいと思います。

% cd projects/complete_project
% python manage.py syncdb
% python manage.py runserver 0.0.0.0:8001

のみでアプリが動きます。

スクリーンキャストを撮ったので、pinaxがどんなものか知りたい方は参考にしてください。

http://www.ueblog.org/media/static/django6_1/django6_1.swf

ではsettings.pyを読んでみましょう。このファイルは文字通り設定ファイルになります。

まずデータベースの定義です。

DATABASE_ENGINE = 'sqlite3'    # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
DATABASE_NAME = 'dev.db'       # Or path to database file if using sqlite3.

pinaxではsqlite3を使い、プロジェクト直下のdev.dbというファイルにデータベースを作るようになっています。

これは、とりあえずすぐに動かせるように設定してあるので、本番環境ではMySQLやpostgresqlなどが良いと思います。

次にINSTALLED_APPS、complete_projectでは、これだけのアプリがインストールされるように定義されています。

INSTALLED_APPS = (
    # included
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.humanize',
    'django.contrib.markup',

    # external
    'notification', # must be first
    'django_openid',
    'emailconfirmation',
    'django_extensions',
    'robots',
    'dbtemplates',
    'friends',
    'mailer',
    'messages',
    'announcements',
    'oembed',
    'djangodblog',
    'pagination',
#    'gravatar',
    'threadedcomments',
    'wiki',
    'swaps',
    'timezones',
    'feedutil',
    'app_plugins',
    'voting',
    'tagging',
    'bookmarks',
    'blog',
    'ajax_validation',
    'photologue',
    'avatar',
    'things',
    'flag',
    'schedule',
    'microblogging',
    'locations',

    # internal (for now)
    'analytics',
    'profiles',
    'account',
    'tribes',
    'projects',
    'misc',
    'photos',
    'tag_app',

    'django.contrib.admin',
)
% python manage.py syncdb

をしたときに、これらのアプリのmodelを探して、その定義に沿ったtableを設定されたDBに作ります。

Webフレームワークの多くはデータベースのtableを定義が先で、それに沿ったmodelをフレームワーク側が作ることが多いようですが、Djangoは逆なのでデータベースの知識がそれほどなくても複雑なモデルを組上げることができます。

そして

% python manage.py runserver

でテストサーバーを動かすことができます。

Djangoを動かす環境とブラウザを動かす環境が違う場合は動画でやったように

% python manage.py runserver 0.0.0.0:8001

サーバーのIPアドレスと8001ポートを使用してテストサーバーが動きます。

0.0.0.0と指定しておくと、そのサーバーのIPアドレスで立ち上がるので便利です。

では、次回は

basic_projectのprofile(basic_profile)をcomplete_projectのものに変更する

をやることによって、

  • アプリを追加したときのsettings.pyの編集
  • urls.pyとurl関数の説明
  • templateの読み込みのルール

を説明してきたいと思います。

categories: pinax, django-handson6, django
Read and Post Comments

track feed ueblog