Sunday, November 25, 2007

adminのオーバーライド2

以前書いたdjangoでadminをオーバーライドする方法がかなりひどい方法だとわかったのでもう一度書くことにした。

いろいろ調べたのだけど
http://code.djangoproject.com/wiki/ExtendingAdminTemplates
に載っているやりかたが非常に簡単。
例えば自分のサイトが

+ mysite
+ admin
+ polls
+ template
+ admin
+ change_list.html

となっていたら以下のようにtemplates のところに admin_copies ディレクトリを作り、そこに change_list.html とかをオリジナルのものからコピーしてくる。

+ mysite
+ admin
+ polls
+ templates
+ admin
+ change_list.html
+ admin_copies
+ change_list.html

そして mysite/templates/admin/change_list.html は admin_copies のものをextends してオーバーライドする。

例えば以下のように

{% extends "admin_copies/change_list.html" %}
{% load adminmedia admin_list i18n %}

{% block search %} < div > Insert your change list message here and there... < /div > {% search_form cl %}{% endblock %}

また以下のようにコピーの替わりにソフトリンクを張っても同じことが可能

ln -s /PATH-TO-DJANGO/django/contrib/admin/templates/admin/change_list.html templates/admin_copies/change_list.html

djangoのインストールディレクトリが固定されている場合はこういう方法もいいかもしれない(別環境持っていったら動かないとかのトラブルもおきそうだけど)。

Friday, November 16, 2007

Django で unittest を実行する方法

追記 2007/11/24
ここに書いたようなややこしい方法をとらないでも
$ python manage.py test
とすればアプリケーションディレクトリ(普通models.py の入ったディレクトリ)に置いたtests.pyというテストファイルを実行することができます。
ドキュメントはきちんと読みましょう orz (tokibitoさんありがとうございます)
http://michilu.com/django/doc-ja/testing/

以下の文章はなんらかの理由で上記のコマンド使いたく無い人か、どうやったらテスト前の環境を自力で設定できるのかを知りたい人向けです(そんな人いるのか?)
--------------------------------------------------------------
Django アプリケーションに対し unittest を実行したときのメモ。
環境設定などに少しコツが必要だった。

django のチュートリアル
Writing your first Django app, part 1
はじめての Django アプリ作成,その 1

に出てくるモデル Poll に対し簡単なunittestを実行してみた。
view のテストとかはまだ行っていない。

ディレクトリの構造は以下のような感じ

mysite
+ settings.py
+ test_start.py
+ polls
+ models.py
+ views.py
+ test
+ polls_test.py

トップディレクトリの mysite に test_start.py が置いてある。ここで環境設定などを行い各ディレクトリのテストプログラム(ここではpolls_test.py)を起動する。このほうが各ディレクトリのテストプログラムに環境設定ルーチンを追加するより簡単だと思う。
環境設定のポイントは
テスト起動プログラム test_start.py に

import settings
from django.core import management
management.setup_environ(settings)

# setup_environ する前にインポートするとエラーを起こす
import django.test.utils

を書くということ。
またテスト用DBを生成するならば main 部分などに

django.test.utils.create_test_db(verbosity=1, autoclobber=True)
django.test.utils.setup_test_environment()

を書いてテスト用データベース(元のデータベースには影響をあたえない)を生成する。

実際に書いたコードは以下のようになった。

test_start.py

import unittest

import django

import settings
from django.core import management
management.setup_environ(settings)
import django.test.utils

from polls.tests import polls_test
from polls.models import Poll
import datetime

from django import newforms as forms
import datetime

def init_test_data():
df = forms.DateTimeField()
cleaned_datetime = df.clean(datetime.datetime.now())

data = Poll.objects.create(question="Are you fine?", pub_date=cleaned_datetime)
data.save()


if __name__ == '__main__':
django.test.utils.create_test_db(verbosity=1, autoclobber=True)
django.test.utils.setup_test_environment()
init_test_data()

# test run
unittest.TextTestRunner().run(polls_test.suite)


polls/test/polls_test.py

import unittest

from polls.models import *

class PollsModelsTestCase(unittest.TestCase):

# setUp は各テストメソッドの実行前に必ず実行されるメソッド
def setUp(self):
self.poll_list = Poll.objects.all().order_by('-pub_date')

# テストメソッド名は必ず test で始める
def testModelNum(self):
# モデルの個数が1であることを検査するだけの超簡単なテスト
self.assertEqual(len(self.poll_list), 1,)
return

def testModelNumNotEqual(self):
# モデルの個数が100でないことを検査するだけの超簡単なテスト
self.assertNotEqual(len(self.poll_list), 100,)
return

suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(PollsModelsTestCase))


テストを実行するには単にtest_start.pyを起動する。

$ python test_start.py



出力結果

Creating test database...

Creating table auth_message
Creating table auth_group
Creating table auth_user
Creating table auth_permission
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table django_admin_log
Creating table polls_poll
Creating table polls_choice
Installing index for auth.Message model
Installing index for auth.Permission model
Installing index for admin.LogEntry model
Installing index for polls.Choice model
Loading 'initial_data' fixtures...
No fixtures found.
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK


参考
Testing Django applications