Hatena::Grouppython

nelnal@python

2009-08-25

[] 「Django Book」をやってみる:Chapter 4 Templates その2 23:11  「Django Book」をやってみる:Chapter 4 Templates その2 - nelnal@python を含むブックマーク はてなブックマーク -  「Django Book」をやってみる:Chapter 4 Templates その2 - nelnal@python

複雑なデータを使用する。

ここでは今までの様な単純なデータを使用してましたが、より複雑なデータをContextクラスに取り込んだ場合でも簡単な記述で使用出来る様に変換する仕組みを備えています。


例えば辞書型の場合

>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': '43'}
>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
>>> c = Context({'person': person})
>>> t.render(c)
u'Sally is 43 years old.'

また、オブジェクトの属性(Attribute)も上手く取り扱うことが出来ます。

>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(1993, 5, 2)
>>> d.year
1993
>>> d.month
5
>>> d.day
2
>>> t = Template('The manth is {{ date.month }} and the year is {{ date.year }}.')
>>> c = Context({'date': d})
>>> t.render(c)
u'The manth is 5 and the year is 1993.'

当然自分で作成したクラスにも対応出来ます。

>>> from django.template import Template, Context
>>> class Person(object):
...     def __init__(self, first_name, last_name):
...             self.first_name, self.last_name = first_name, last_name
... 
>>> t = Template('Hello, {{ person.first_name }}.')
>>> c = Context({'person': Person('John', 'Smith')})
>>> t.render(c)
u'Hello, John.'

さらにオブジェクトのメソッドについても使用可能です。

丸括弧を付ける必要はありません。

>>> from django.template import Template, Context
>>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
>>> t.render(Context({'var': 'hello'}))
u'hello -- HELLO -- False'
>>> t.render(Context({'var': '123'}))
u'123 -- 123 -- True'

最後に配列の要素へのアクセス方法についても記載します。

>>> from django.template import Template, Context
>>> t = Template('Item 2 is {{ items.2 }}.')
>>> c = Context({'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
u'Item 2 is carrots.'


メソッド呼び出し時の振る舞い(例外の処理について)

メソッドの呼び出しについては他の属性の呼び出しと似ている部分が多いですが、

メソッドの処理に失敗した場合の振る舞いが違ってきます。


メッソドの実行中に例外が発生した場合は通常のPythonプログラムと同様に処理を中断して例外の発生をメッセージとして表示します。

しかし、raiseする例外クラスの属性「silent_variable_failure = True」を追加した場合は、例外の発生を無視して空のデータを返して実行を継続することが出来る。

>>> t = Template("My name is {{ person.first_name }}.")
>>> class PersonClass3:
...     def first_name(self):
...             raise AssertionError, "foo"
...
>>> p = PersonClass3()
>>> t.render(Context({"person": p}))
Traceback (most recent call last):
   ...
AssertionError: foo
>>> # 例外の発生を無視する
>>> class SilentAssertionError(AssertionError):
...     silent_variable_failure = True
...
>>> class PersonClass4:
...     def first_name(self):
...             raise SilentAssertionError
... 
>>> p = PersonClass4()
>>> t.render(Context({"person": p}))
u'My name is .'

また、ここであるオブジェクト(ここでは BankAccount とする)が delete メソッドを持っているとします。

もしテンプレートが {{ account.delete }} を含んでいた場合*1にテンプレートを展開しようとするとオブジェクトが削除されてしまうことになってしまいます。

もしこれを防ごうとする場合、delete メソッドに alters_data という属性を付与し、値を True にすることによって対処します。

def delete(self):
    # Delete the account
    ...
delete.alters_data = True

これによってテンプレートを展開する際にメソッドを実行出来なくなります。

上記の例で言うと {{ account.delete }} を展開する際に delete メソッドは実行されず、また警告も出ずに失敗することになります。



Next --> Chapter 4 その3

*1:account は BankAccount のインスタンス

トラックバック - http://python.g.hatena.ne.jp/nelnal_programing/20090825

2009-08-19

[] 「Django Book」をやってみる:Chapter 4 Templates 22:55  「Django Book」をやってみる:Chapter 4 Templates - nelnal@python を含むブックマーク はてなブックマーク -  「Django Book」をやってみる:Chapter 4 Templates - nelnal@python

テンプレートのサンプル

<html>
<head><title>Ordering notice</title></head>

<body>

<h1>Ordering notice</h1>

<p>Dear {{ person_name }},</p>

<p>Thanks for placing an order from {{ company }}. It's scheduled to 
ship on {{ ship_date|date:"F j, Y" }}.</p>

<p>Here are the items you've orderd:</p>

<ul>
{% for item in item_list %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

{% if ordered_warranty %}
    <p>Your warranty infomation will be included in the packaging.</p>
{% else %}
    <p>You didn't order a warranty, so you're on your own when 
    the products inevitably step working.</p>
{% endif %}

<p>Sincerely,<br />{{ company }}</p>

</body>
</html>

解説

上記文書の内、中括弧({,})で囲まれた部分は変数となります。

{{ person_name }}


{% for item in item_list %}

...

{% endfor %}


{% if ordered_warranty %}

...

{% else %}

...

{% endif %}

中括弧の中に記載された名前がキーワードとして使用されることになります。


{%」と「%}」に囲まれた部分は値によって処理の切り替えの為のテンプレート記法です。

{% if ordered_warranty %}


forはsequenceタイプのデータを渡して格納されている要素を個別に文書に反映する為に使用します。

ifは変数として渡したデータが有効かどうか(True判定になるか)で表示(またはその他の処理の記述)を切り替える為に使用します。


また、変わった使用方法として第2段落のテンプレート記法があります。

{{ ship_date|date:"F j, Y" }}

これは日付データ*1の表示形式を変更する記法です。


テンプレートシステムを試してみる。

ここではシェルを使ってテンプレート記法とその変換処理を試してみます。

シェルで

$ python manage.py shell

と打ってシェルを実行します。

この様にシェルを呼び出さないと django モジュールを呼び出すことが出来ません。


それではテンプレートのテストをしてみます。

>>> from django import template
>>> t = template.Template('My name is {{ name }}.')
>>> c = template.Context({'name': 'Adrian'})
>>> print t.render(c)
My name is Adrian
>>> c = template.Context({'name': 'Fred'})
>>> print t.render(c)
My name is Fred.


Next --> Chapter4 その2

*1:datetimeモジュール使用

トラックバック - http://python.g.hatena.ne.jp/nelnal_programing/20090819

2009-08-04

[] 「Django Book」をやってみる : Chapter 3 Views and URLConf その2 11:24  「Django Book」をやってみる : Chapter 3 Views and URLConf その2 - nelnal@python を含むブックマーク はてなブックマーク -  「Django Book」をやってみる : Chapter 3 Views and URLConf その2 - nelnal@python

URL設定ファイルの指定(切り替え)方法

この設定も mysite/settings.py に記述されています。

ROOT_URLCONF = 'mysite.urls'

初期設定で既に mysite/urls.py が指定されているので mysite/urls.py にURLパターン記述しただけで hello world を表示させることが可能だったのです。


同様に別のファイルにURLパターン情報を記述し、それを ROOT_URLCONF の参照先に設定・使用することも可能です。


Django の表示リクエストの処理の流れ

ここでは hello/ の表示を要求された場合の処理について記述する。

  1. hello/ についての表示リクエストを受け取る
  2. アプリケーションRootディレクトリにある settings.py の中に記述された ROOT_URLCONF の値を参照して、URL設定ファイルを決定する。
  3. URL設定ファイルの urlpatterns と hello/ を比較し、一致するものを見つける(1つ見つければ良い)。
  4. 一致する項目の表示処理(view)を呼び出す。
  5. 表示処理が HttpResponse インスタンスを戻す。
  6. Django が HttpResponse を変換してWebページに表示できる形式に変更する。

動的なページの表示(現在時刻を表示する)

Webで「Hello, world!」を表示するだけならHTMLを理解していればいっこうに問題はありません。

スクリプト言語をWebで利用する理由の1つは

ユーザーからの要求に応じて変更を施したWebページを表示することにあります。

そこで今度はユーザリクエストが行われた時刻を表示する処理を作ってみます。


以下の関数mysite/views.py に追記して下さい。

import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

mysite/urls.py には以下を追記

from mysite.views import current_datetime

urlspatterns += ('',
    (r'^time/$', current_datetime),
)

ここまで記述したらサーバーの動作を確認*1し、http://localhost:8000/time/アクセスしてみます。

「It is now (現在時刻)」と表示されれは成功です。


同じ処理を別のURLで行う

別のURLでも同じスクリプトを動かしたい場合の記述です。

と、言っても mysite/urls.py に以下の様に別のURLに同じスクリプトを割り当てるだけでOKです。

urlpatterns += ('',
    (r'^time/$', current_datetime),
    (r'^another-time-url/$', current_datetime),  # 追加
)

http://localhost:8000/another-time-url/アクセスしてみて http://localhost:8000/time/ と同じ様なページが表示されればOKです。



URLに記述された値を使って動的にページを表示する

今度は少し時間を進めたページを作ってみます。

それぞれ1時間、2時間、3時間、4時間時計を進めた時刻を表示するページを用意するものとし、URLにはそれぞれの進めている時間数(1, 2, 3, 4)を含めるものとします。


仮に mysite/urls.py を以下の様に記述してみます。

urlpatterns += patterns('',
    (r'^time/$', current_datetime),
    (r'^another-time-url/$', current_datetime),
    (r'^time/plus/1/$', time_plus_1),  # 追加。関数は未定義
    (r'^time/plus/2/$', time_plus_2),  # 追加。関数は未定義
    (r'^time/plus/3/$', time_plus_3),  # 追加。関数は未定義
    (r'^time/plus/4/$', time_plus_4),  # 追加。関数は未定義
)

既にお分かりの通り、この方法は賢い方法とは言えません。

もし、「時計を5,6,7,8時間進めた表示を行いたい場合」や「時計の進みを100時間まで1刻みで表現したい場合」に作業の手間が発生してしまいます。


そこで、以下の方法を取ることによってこの問題を解決します。

  • URL表記を一般化する → 正規表現を使用する
  • URLに書かれた値を取得して表示処理を行う

URL表記を一般化する

既にChapter 3 その1でも書いた通りURL表記には正規表現が使用可能です。

例えばこの様に記述できます。

(r'^time/plus/\d/$', time_plus),

しかし、上記の記述では time/plus/100000000 というURLにも対応されてしまいます。


ここでは2桁までに制限することとして以下の様に記述することにします。

(r'^time/plus/(\d{1,2})/$', time_plus),

(上記に対応した mysite/urls.py の記述(後部)は以下の様になります。)

urlpatterns = patterns(''
    (r'^time/$', current_datetime),
    (r'^another-time-url/$', current_datetime),
    (r'^time/plus/(\d{1,2})/$', hour_plus),  # 変更。対応関数は後述
)

URLに書かれた値を取得して表示処理を行う

それでは今度は指定された値の分、時間を進めた時刻表示処理を記述します。

以下の関数mysite/views.pyに記述して下さい(current_datetime 関数の後に記述して下さい)

from django.http import Http404

def time_plus(request, offset):
    try:
        offset = int(offset)
    except ValueError:   # int(offset)に失敗した場合、404 Errorを返す
        raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    html = "<html><body>It is now %s</body></html>" % dt
    return HttpResponse(html)


動作確認

サーバー起動状態を確認(python manage.py runserver)後、動作確認を行います。

以下のURLの表示と表示された時刻をそれぞれ確認して下さい。


また、以下のURLの表示がエラーになることを確認して下さい。


表示関数引数の取り方について

こちらは Chapter 8 にて詳細に説明を行います。



これで Capter 3 は終了です。

Next ---> Chapter 4

*1python manage.py runserver

トラックバック - http://python.g.hatena.ne.jp/nelnal_programing/20090804

2009-08-02

[] 「Django Book」をやってみる : Chapter 3 Views and URLConf その1 23:18  「Django Book」をやってみる : Chapter 3 Views and URLConf その1 - nelnal@python を含むブックマーク はてなブックマーク -  「Django Book」をやってみる : Chapter 3 Views and URLConf その1 - nelnal@python

Django Book
http://www.djangobook.com/en/2.0/

Hello world!

表示ページの作成

まずは前回作成した mysite のディレクトリに views.py というファイルを作成します。

次に views.py を編集します。

# -*- coding: utf-8 -*-
from django.http import HttpResponse

def hello(request):
    return HttpResponse("Hello world!")


URLの設定

次に URL の設定をします。

URL の設定は mysite ディレクトリ内の urls.py に記述します。

from django.conf.urls.defaults import *

# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',
    # Example:
    # (r'^mysite/', include('mysite.foo.urls')),

    # Uncomment the admin/doc line below and add 'django.contrib.admindocs' 
    # to INSTALLED_APPS to enable admin documentation:
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    # (r'^admin/', include(admin.site.urls)),
)

(上記は urls.py の初期状態)


初期状態では不要なコメントが多数あってこれを残したまま解説するのは大変なので削除します。

from django.conf.urls.defaults import *

urlpatterns = patterns('',
)

ここに views.py に書いた「Hello world!」を表示する為の設定をします。

from django.conf.urls.defaults import *
from mysite.views import hello

urlpatterns = patterns('',
    (r'^hello/$', hello)
)

これで表示の為の処理は完了です。


確認

これで「Hello world!」の表示が可能になったので確認します。

確認するURLhttp://localhost:8000/hello/ です

("python manage.py runserver"を実行してなかったら実行してください)。


いくつかのポイント

views.py について

  • views.py に記述されるのはURLを呼ばれた時に表示処理を行う関数(もしくはそのサブルーチン)です。
  • 表示処理を行う関数の名前はURL上で表現する文字列と同一である必要はありません。関数名は開発者が自由につけることができます。
  • 表示処理を関数は必ず1つの引数をとります。この引数は表示処理関数を割り当てた URL を呼び出す際に付加された情報を持っています(詳細は後述)。

urls.py について

  • urls.py はURLと表示処理関数を紐付けする為の設定を記述します。
  • URLと表示処理関数の紐付け情報は urlspattern に格納されます。また urlspattern にデータを入れる際には pattern 関数を使わなければなりません。

ursl.py の pattern 記述について

  • pattern 関数内で「^」とか「$」が使われているが、これはURL表現に正規表現を使ってるため。
  • 「^」が入ってない場合、終端に「/hello/」を含んでいるURLは全て mysite.views.hello が表示に使われることになります。
  • 「$」が入ってない場合は、先頭に「/hello/」が含まれていればそれ以降にどのような文字列URL に含まれていても mysite.views.hello が表示に使われることになります。
urlpatterns = patterns('',
    (r'^hello/', hello ),    # この場合、http://localhost:8000/hello/ から始まるURLであれば何でも良い
                             #   http://localhost:8000/hello/a
                             #   http://localhost:8000/hello/test/test/
)
urlpatterns = patterns('',
    (r'hello/$', hello ),    # この場合、hello/ で終わるURLであれば何でも良い
                             #   http://localhost:8000/20090802/hello/
                             #   http://localhost:8000/test/abc/hello/
)

尚、正規表現の使い方は Python の re モジュールに依存しているのでそちらを参照にして下さい。


サイトのトップ URL の指定方法

サイトのトップ(http://localhost:8000/)にアクセスした際に動作させるスクリプトを指定するには以下の様に記述します。

urlpatterns = patterns('',
    (r'^$', script ),
)


これで Chapter 3 その1 は終了です。

Next --> Chapter 3 その2

トラックバック - http://python.g.hatena.ne.jp/nelnal_programing/20090802

2009-08-01

[] 「Django Book」をやってみる 導入編 20:15  「Django Book」をやってみる 導入編 - nelnal@python を含むブックマーク はてなブックマーク -  「Django Book」をやってみる 導入編 - nelnal@python

Django を始めてみようと思って本とか色々と検討したのだが、結局ネットにあった""Django Book""というのをやってみることにした。

Django Book
http://www.djangobook.com/en/2.0/

日本語訳のものもあったが、どうやら途中の様なので英語版の方で頑張ってみることにする。

Django の利便性

  1. 動作確認をする段階では別にサーバーを用意する必要が無い(Pythonサーバ機能を利用する)。
  2. 大規模なDB環境が不要なのであれば SQLite を使用すれば良い(SQLite のデータはファイル形式なので管理が楽)。
  3. 管理ツールが非常に使いやすい(らしい)。
  4. その他のWebフレームワークと同等の機能はある。

[] 「Django Book」をやってみる Chapter1: Intoroduction to Django 19:34  「Django Book」をやってみる Chapter1: Intoroduction to Django - nelnal@python を含むブックマーク はてなブックマーク -  「Django Book」をやってみる Chapter1: Intoroduction to Django - nelnal@python

フレームワークの利便性の解説。

特に設置・利用についての重要な説明はないので省略


[] 「Django Book」をやってみる Chapter2: Getting Started 19:34  「Django Book」をやってみる Chapter2: Getting Started - nelnal@python を含むブックマーク はてなブックマーク -  「Django Book」をやってみる Chapter2: Getting Started - nelnal@python

Python のバージョンの確認

まず最初に Django を使用する為の環境があるかどうか確認します。

Django の実行には Python 2.3 以上の環境が必要なので Python のバージョンを確認します。

バージョンの確認には Python の起動をするのが一番手っ取り早いです。

(下記は MacOSX 10.5.7 で実行。以降も同様)

$ python

'import site' failed; use -v for traceback

Python 2.5.1 (r251:54863, Feb 6 2009, 19:02:12)

[GCC 4.0.1 (Apple Inc. build 5465)] on darwin

Type "help", "copyright", "credits" or "license" for more information.

>>>

もし、Pythonが入ってないようであればインストールしてください。


Django フレームワークダウンロードしてインストール

Django の本家ページから Djangoモジュールダウンロードします。

Django Project
http://www.djangoproject.com/

ちょうど7/29に Version 1.1 が出ているのでそれを使ってみることにします。


まずは解凍して、その後インストールを行います。

$ tar zxvf Django-1.1.tar.gz

'''(省略)'''

$ sudo python setup.py install

'''(省略)'''

$

尚、Windows の場合は 7-Zip などで解凍して、

setup.py が置かれているフォルダで「python setup.py install」と入力して実行してインストールをします*1


インストールが済んだらモジュールがちゃんと呼び出せることを確認します。

$ python

'import site' failed; use -v for traceback

Python 2.5.1 (r251:54863, Feb 6 2009, 19:02:12)

[GCC 4.0.1 (Apple Inc. build 5465)] on darwin

Type "help", "copyright", "credits" or "license" for more information.

>>> import django

>>> django.VERSION

(1, 1, 0, 'final', 0)


また「django-admin.py」が実行出来ることも確認します。

$ django-admin.py help

コマンドが見つからない などのメッセージが出た場合は、django-admin.py のあるフォルダを環境変数 PATH に追加する。

MacOSの場合は /usr/local/bin に、Windows の場合は '''(Pythonインストールパス)'''/Scripts にある。



DBの設定について

ここでは SQLite を使用する予定なのでここでは特に説明しません。省略。



プロジェクトの作成

それではテストプロジェクトを作成します。

django-admin.py の startproject コマンドを実行します。

$ django-admin.py startproject mysite


上記コマンドを実行するとコマンドを実行したディレクトリに「mysite」というディレクトリが作成されます。

ディレクトリの中には4つのファイルが作成されています。

  • mysite/
    • __init__.py
    • manage.py
    • settings.py
    • urls.py

__init__.py
mysite ディレクトリの中身をパッケージとして認識させるのに必要なファイル。中身は空。
manage.py
プロジェクトで様々な処理を実行する為のユーティリティプログラム
settings.py
プロジェクトの設定情報(DB関連、参照モジュール、参照テンプレート)を記述するファイル。
urls.py
プロジェクト以下のURLの管理をする為の設定ファイル。

開発用サーバーを起動する

開発用サーバーで mysite を起動します。

$ cd mysite

$ python.py manage.py runserver

サーバーを起動したら http://localhost:8000/アクセスして、正常に動作していることを確認しましょう。

「It Worked!」の表示が出ればOK。


尚、使用するポートを変更したい場合は以下の様に起動します(以下は Port 8080 を使用したい場合)。

$ python manage.py runserver 8080

また、ローカルネットワーク上で公開したい場合はIPアドレスも一緒に指定します。

$ python manage.py runserver 192.168.XXX.XXX:8080



Chapter 2 はここまで。

Next --> Chapter 3 その1

*1環境変数 PYTHONPATH が設定されてなければいけない

トラックバック - http://python.g.hatena.ne.jp/nelnal_programing/20090801