Tag/Django

django-pistonでRestfulなWebAPIを簡単につくる

先日Twitterでつぶやいてたdjango-pistonですが、グーグル先生に聞いても日本語の記事はほとんど見つからなかったんで、わたくしが書いてみようと思います。

django-piston はもともとBitbucketのWebAPIのために作られた(多分)もので既存のDjangoのモデルを利用して簡単にRestfulなWebAPIが作れるという代物です。個人的には、いつか使ってみようと思いながら機会がなかったんですが、最近iPhoneアプリ作ってて、サーバ側の実装に使えそうだと思ったので使ってみました。

主な機能としては、

  • RestfulなWebAPIっぽく、GET POST PUT DELETE を受けれる
  • 1時間に50回までとかAPI呼出回数の制限をデコレータでつけられる
  • ベーシック認証とOAuth認証に対応
  • ドキュメント生成
  • Djangoのformを利用したバリデーション

今回は、だいぶ前に @soundkitchen 氏に作ってもらったこのブログを使って実験してみます。ちなみにこのブログのソースは bitbucket にて公開しはじめました。場当たりでDjangoのバージョンアップにだけ対応してきたのでちょっと古いコードとかもありそうだし、いろいろいじりたいと思ってます。

今回の動作サンプルはこちら

そしたらこのブログのエントリーを取得できるようなAPIを書いてみます。現在のエントリー部分のモデルは、↓のような感じです。とりあえずこの中からいくつかのフィールドを持ってくるようにしてみます。

class Entry(models.Model):
    """
    blog's entry.
    """
    title = models.CharField(_(u'title'), max_length=255, default=None)
    slug = models.SlugField(_(u'slug'))
    description = models.TextField(_(u'description'))
    comments_count = models.IntegerField(_(u'comments count'), editable=False, default=0)
    trackbacks_count = models.IntegerField(_(u'trackbacks count'), editable=False, default=0)
    created_at = models.DateTimeField(_(u'created at'), editable=False, default=datetime.now)
    updated_at = models.DateTimeField(_(u'updated at'), editable=False)
    published_at = models.DateTimeField(_(u'published at'), editable=False, blank=True, null=True)
    is_published = models.BooleanField(_(u'is published'), default=True)
    is_active = models.BooleanField(_(u'is active'), default=True)
    tags = models.ManyToManyField(Tag)

とりあえず、django-pistonのインストール。最新版は0.22なんですが、これだとDjango1.2以降でPOSTするときにCSRF用のトークンがないって言われて動かないのでtip版の0.23rc1を使ってます。

まずは、プロジェクトのルートにapiというディレクトリとurls.py、handlers.py をそれぞれ作成します。

$ mkdir api
$ touch api/__init__.py
$ touch api/urls.py
$ touch api/handlers.py

次に、プロジェクトルートのurls.pyに手を加えます。

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

これを追記して、/api/以下へのアクセスは、api/urls.pyに丸投げしましょう。そして、api/urls.pyの中身は↓のような感じ。

from django.conf.urls.defaults import *
from piston.resource import Resource

from api.handlers import EntryHandler

entry_resource = Resource(EntryHandler)

urlpatterns = patterns('',
    (r'^posts/$', entry_resource),
    (r'^post/(?P<entry_id>\d+)/$', entry_resource),
)

EntryHandlerはこれからapi/handlers.pyに書くやつです。ここでは、/api/posts/ に来たときと /api/post/1/ とかに来たリクエストをさばく設定をしました。そして、api/handlers.py は↓な感じ

#vim:fileencoding=utf8
from piston.handler import BaseHandler

from blog.models import *


class EntryHandler(BaseHandler):
    """
    ブログのエントリーを返す
    """
    allowed_methods = ('GET',) # GETだけ受けつける
    fields = ('title', 'description', 'created_at', 'updated_at', 'get_absolute_url', 'tags') # 取得したいフィールド
    exclude = () # 除外するフィールド(これを空にしておかないとデフォルトでは、idが省かれる)
    model = Entry # モデル

    def read(self, request, entry_id=None):
        """
        entry_idがある場合は単一のエントリー。
        なければ最新の10個。
        """
        if entry_id:
            try:
                instance = Entry.objects.get(pk=int(entry_id))
            except Entry.DoesNotExist:
                return rc.NOT_FOUND # 404 を返すショートカット
        else:
            return Entry.objects.all()[:10] # 10個もってくる
        return instance

とりあえずこんな感じで動きます。GETのリクエストを受けるのがreadメソッドとかPOSTを受けるのが、createメソッドとかっていう決まりがあるんですが、今回はとりあえずGETだけ受けつけるようになってます。ちなみに、デフォルトではJSONでレスポンスが返るんですが、/api/posts/?format=xml とかするとXMLで返してくれます。

今回は疲れたのでここまでで、次はPOSTとかPUTとかDELETEも受け付けてみようと思います。

Posted at: 
2010/10/31 16:31:07
0 Comments
1 TrackBack
Tags: 
Django
Trackback: 
http://blog.monospace.jp/2010/10/31/django_piston_intro/trackback/

Djangoでファイルアップロードのエラー

Python 旅館に来ています。過去にはまったことはメモっておくべきと思ったので、マメにブログに書いていこうと思いました。

とりあえず、 ImageField を含む適当なモデルを書いて、管理画面から追加したところ、画像のアップロードができません。というエラーの話。

環境は、MacOSX 10.5 Python2.5.1 Django1.0.2 です。

エラー内容は、「画像をアップロードしてください。アップロードしたファイルは画像でないか、または壊れています。」というもの。このエラーを django/conf/locale/ja/LC_MESSAGES/django.po から探すと、 django/forms/fields.py に書いてあるとのこと。なるほど、とりあえずPILが認識できない画像があがってくると、このエラーメッセージが出るっぽい。

要するに Python Image Library が JPEG を扱えなかったようですね。

$port install jpeg

Port で Jpeg 操作用のライブラリをインストールして、 PIL のインストールをし直して完了。その際に PIL の setup.py install でできた build ディレクトリとか消した方がいいですね。無事にアップロードできました。

Posted at: 
2009/01/31 02:12:04
0 Comments
0 TrackBacks
Tags: 
Django
Trackback: 
http://blog.monospace.jp/2009/01/31/django_file_upload_error/trackback/

Django勉強会 Disc7 に参加しました

Django勉強会 Disc7 http://djangoproject.jp/etude/7/

会場提供は、 株式会社アクセンス・テクノロジー さん。 立派なメモ帳まで頂いてしまいました。

久々の開催ということで東京まで行ってきました。今回は、初心者向けのDisc6との同時開催だったんですが、Disc7の中級の方に参加してきました。顔ぶれが割と新鮮な感じがしたのは、Djangoが広まってきてるってことなのかなー。

GeoDjango - tmatsuo さん

Django で地図上の情報を扱う GeoDjango について解説してくれました。 GeoDjango は、Django1.0 から標準で contrib/gis として含まれていて具体的には、地図上にポイントを置いたり、線を引いたり、エリアを作ったりして、経路情報や距離の測定、面積の計算とかそんなことが Django 風にできるっぽいです。なんかすごく夢が広がりますね。Django の管理画面上に地図が表示されてそこでマウスのドラッグアンドドロップで操作ができるっていうのがすごいですね。あと、国境のデータとかもあるみたいでかなりすごいことできそうです。

GenericForeignKey - ymasuda さん & ContentTypes - tokibito さん

通常の ForeignKey とは違って特定のモデルへのリレーションではなく、存在しているどれかのモデルへのリレーションを貼るというモデルフィールド。逆参照は自動で貼られないので、明示的にする必要あり。これが GenericRelation。GenericRelation は1つのリレーション先しか指定できないが、その辺はモデルの継承を使うことでうまくできるっぽい。 Django の組み込みのライブラリでもこの機能は結構使われている。contrib/comment とか。

名前は知ってたけど使ったことがない機能だったんだけど、ちょうど前日に仕事で Django を書いてたら必要性を感じたというタイミングでのタイムリーな話題でした。自分の中で予想してたこととだいたいあってたんで、結構理解できました。さらに tokibito さんのデモでより理解できた感じです。これは今後使いそうだなー。要勉強。

DjangoでOpenIDに対応 - isle さん

OpenIDの仕組みについてほとんど知らなかったんで学べるいい機会でした。認証の流れは結構複雑だけど、ライブラリを使えば割と簡単に実装できるとか。mixi の場合はニックネームが取れるとか、 Yahoo では取れないとか。

ライブコーディング - perezvon さん

Django で某携帯サイトに追加の機能を実装するというすごいライブコーディング。他人が Django のコーディングをしている様子が見れるだけでも勉強になったけど、具体的なところでは、ステートレスを活かした URL の実装とか勉強になった。実際今、 Django で携帯サイト作ってるからその辺のノウハウとか聞きたかったなー。クッキー使わないセッションとかなにげに今書いてる。

そんなわけで色々と勉強になりました。こういう機会を作ってくださった主催側の方々ありがとうございます。また今度もよろしくお願いします。と同時に名古屋でも Django 勉強会やりたいなーと思った。人集まらないかな…

Posted at: 
2009/01/18 03:06:30
2 Comments
0 TrackBacks
Tags: 
Django
Trackback: 
http://blog.monospace.jp/2009/01/18/django_ja_disc7/trackback/

Fabric で Django アプリのデプロイ

Google App Engine のデプロイの簡単さを知ってからというもの Django アプリのデプロイもあのくらいにならないものかと思っていたわけですが、ちょっと Fabric というデプロイツールを見つけたので使ってみました。 Capistrano 的なものということですが、 Capistrano は使ったことがありません。 Fabric は Python 製ということで困った時のソース読みが可能なのでちょっと遊んでみることにしました。

Fabric

インストール

easy_install で一発です。これで /usr/local/bin/fab というコマンドがインストールされます。動作環境は、Leopard のデフォルト Python2.5.1 です。

$ sudo easy_install fabric
$ fab

fabfile.py の作成

デプロイ処理を fabfile.py というファイルに記述します。ここで書いた関数は、 $ fab コマンド名 のコマンド名部分になります。

SSH でログインして、リポジトリから最新版をもってきて、Apache をリロードするって流れを作ります。あ、その前にテストを通ったらってのも重要ですね。

今回リモートに使ってるサーバは、Ubuntuのちょっと前のやつです。(なにかわすれた)

#vim: fileencoding=utf8:

def pull():
    "リポジトリから最新版を取得"
    run('cd $(project_dir); hg pull')

def test():
    "テストを実行"
    local('python manage.py test', fail='abort')

def reload():
    "Apacheのリロード"
    sudo("/etc/init.d/apache2 reload")

def staging():
    "ステージングサーバを選択"
    set(fab_hosts = ['stg.co-soku.jp'])
    set(project_dir = '~/www/stg.co-soku.jp')

def production():
    "プロダクションサーバを選択"
    set(fab_hosts = ['co-soku.jp'])
    set(project_dir = '~/www/co-soku.jp')

今のところ easy_install で入るバージョンだと、set という fabric の関数を使ってるんですが、これは、最新のリポジトリでは、 config.fab_hosts という形式に変更になってるっぽいです。組み込みの set とかぶりますからねえ。ちなみに、set()で設定したものは、$()で取得できます。 $ なんて Python っぽくないかも。

local 関数は、ローカルでの実行。run 関数は、リモートでの実行。 sudo 関数は、リモートで sudo 使う場合のやつです。ちなみに、SSH の接続でパスフレーズなしのキーを使ってると、sudo の実行の時にパスワードが聞かれない問題があるみたいです。というわけで自分は、visudo で apache の再起動コマンドだけを NOPASSWD 設定にしました。

test コマンドは、fail というキーワード引数を渡して失敗した場合の処理を決めます。 'abort' は処理を中断。'ignore' は無視して次の処理へ。 'warn' は、エラーを吐いて進むって感じです。

使い方

Django の プロジェクトルートに fabfile.py を置いて実行します。

テストして、ステージングに接続して、hg pull して、 Apache のリロードという流れを実行します。この場合、test のときに fail='abort' を設定しているので、テストがこけるとそこでデプロイは中断されます。

$ fab test staging pull reload

これだと、以下のようにテストを飛ばせてしまうので、staging や production コマンドの中に、 invoke(test) とか書いておくと、いいかもって書いてありました。

Deploying Django with Fabric @ Irrational Exuberance

$ fab staging pull reload

他のデプロイツールを使ったことがないのでなんとも言えませんが、普通に使えるなあと思いました。

Posted at: 
2008/12/08 01:24:33
0 Comments
0 TrackBacks
Tags: 
Django
python
Trackback: 
http://blog.monospace.jp/2008/12/08/deploy_django_apps_with_fabric/trackback/

django-command-extensions で manage.py のコマンドを色々拡張する

django-command-extensions - Google Code

という manage.py のコマンドの拡張をいっぱい集めたプロジェクト(名前がdjango-extensionsに変更になるみたいです)があるというのを、

Screencast: Django Command Extensions | Surfing in Kansas

のブログで知ってちょっと面白そうなんで、いじってみることにしました。多分ここのブログを見た方が伝わるとおもいます。

まずはインストール

  • まずは、GoogleCodeからダウンロード。
  • 解凍して、できたディレクトリに移動。
  • python setup.py install を実行
  • 使いたいプロジェクトの settings.py の INSTALLED_APPS に、'extensions' を追加。(公式のドキュメントだと、'django_extensions'を追加って書いてあるけど、setup.py でいれると extensions になるっぽいです。)

これで色々と拡張された manage.py が使えるようになります。

例えば…

create_app
新しいアプリケーションを作るときに、startapp を使いますが、これを使うと、--template で新しいアプリケーションのテンプレート構造を指定して作成できます。要するに最初から、forms.pyとかadmin.pyのファイルが作られた状態のアプリケーションができあがるという話です。
describe_form
python manage.py describe_form guestbook.guestbook > guestbook/forms.py こんな感じに使えます。
generate_secret_key
settings.py に書く secret_key を作ってくれます。
graph_models
モデル相関図を表した GraphViz dot file を作ってくれます。
passwd
auth_user のユーザのパスワード変更ができます。
print_user_for_session
session key を渡すと中身を表示してくれます。
runserver_plus
runserver がパワーアップします。Werkzeugが必要ですが、デバッグが超便利になるかも。上記ブログのスクリーンキャストで紹介されてます。
shell_plus
個人的に今すぐ使いたいレベル。モデルを全部インポートした状態で、Python シェルを起動。
sqldiff
まだ実験段階っぽいけど。現在のモデルと実際の DB を比べて SQL の diff を出しくれる。

他にもまだあるっぽいです。JobsSchedulingっていうのが気になるけどまだ見てないです。あと、Field とか Model もあるみたいです。 TimeStampedModel っていう作成時間と更新時間が入ったベースモデルは割と便利かも。

というわけで Django は楽しいです。

Posted at: 
2008/10/29 23:35:58
2 Comments
1 TrackBack
Tags: 
Django
Trackback: 
http://blog.monospace.jp/2008/10/29/django_command_extensions/trackback/

Django Evolution で Model の変更をデータベースに反映させる その2

Stored evolutions

もうちょっとマニュアルを読んだので、 前回 の続きを書いてみます。前回は、

$ python manage.py evolve --hint --execute

で、実行しましたが、一旦ファイルに保存してから行う、 Stored evolutions という方法も試してみます。モデルを作って、変更するところまでは、まったく同じです。最初の syncdb を行って、モデルを変更した後、まず、guestbook アプリケーションディレクトリに evolutions ディレクトリ(モジュール)を作って、次のように evolve --hint の出力を evolutions ディレクトリ内のファイルに書き出します。

$ mkdir guestbook/evolutions
$ python manage.py evolve --hint > guestbook/evolutions/add_tags_and_is_public.py

evolutions/add_tags_and_is_public.py

#----- Evolution for guestbook
from django_evolution.mutations import *
from django.db import models

MUTATIONS = [
    AddField('GuestBook', 'tags', models.CommaSeparatedIntegerField, initial='', max_length=255),
    AddField('GuestBook', 'is_public', models.BooleanField, initial=True)
]
#----------------------
Trial evolution successful.
Run './manage.py evolve --hint --execute' to apply evolution.

あ、↑の最後の2行はいらないですね。消しておきましょう。次に、evolutions 内に __init__.py を設置します。 __init__.py には、↓のようなことを書きます。これは、実行する evolution ファイルのリストです。複数ある場合は、複数指定できます。

SEQUENCE = ['add_tags_and_is_public']

これで、

$ python manage.py evolve

を実行します。ここでは、単に、 evolve だけで大丈夫です。勝手に、guestbook アプリ内の evolutions モジュールを読み込んでくれます。で、以下のように出力されます。これは、 --hint のときの出力とほぼ一緒ですね。最後の1行が違います。

#----- Evolution for guestbook
from django_evolution.mutations import *
from django.db import models

MUTATIONS = [
    AddField('GuestBook', 'tags', models.CommaSeparatedIntegerField, initial='', max_length=255),
    AddField('GuestBook', 'is_public', models.BooleanField, initial=True)
]
#----------------------
Trial evolution successful.
Run './manage.py evolve --execute' to apply evolution.

evolve だけでは、実際の処理は行われないので、 --execute をつけて実行します。

$ python manage.py evolve --execute

yes と答えると、データベースに反映されます。前回と同じようにデータは無事に残っています。

sqlite> select * from guestbook_guestbook;
test|2008-10-13 14:46:31.744999|1|hfunai||1

これで、テスト環境での動作が確認できれば、本番環境でも同じように、 ./manage.py evolve を実行したらいいので、楽になりそうです。これは使える。きっと使える。次回は、SQL で evolutions を保存しておく方法の予定です。

Posted at: 
2008/10/15 04:31:34
0 Comments
0 TrackBacks
Tags: 
Django
Trackback: 
http://blog.monospace.jp/2008/10/15/django_evolution_2/trackback/

Django Evolution で Model の変更をデータベースに反映させる

久々に ReviewBoard をチェックしてたら、 Django Evolution を使ってることを知りました。んで、この Django Evolution は何をしてくれるものかと調べてみたら、 Model の変更をデータベースに反映させてくれるものってことが分かって早速試してみました。

とりあえず、適当にプロジェクト&アプリ作成。Djangoは、1.0 で動かして欲しいみたいです。

$ django-admin.py startproject djtest
$ cd djtest
$ python manage.py startapp guestbook # なんでもいいけど、 guestbook とかつくる。
$ vim guestbook/models.py # guestbook の Model を書く。

guestbook/models.py はこんな感じ。

from django.db import models

class GuestBook(models.Model):
    name = models.CharField(max_length=20)
    comment = models.TextField()
    posted_date = models.DateTimeField()

    class Meta:
        pass

    def __unicode__(self):
        return self.name

Django Evolution をチェックアウトしてプロジェクトディレクトリにコピー、 settings.py を書く。

$ svn checkout http://django-evolution.googlecode.com/svn/trunk/ django-evolution
$ cd django-evolution && cp -r django_evolution /path/to/djtest # プロジェクトディレクトリにコピー
$ vim settings.py # データベースの設定とかしつつ、 INSTALLED_APPS に 'django-evolution' を追加。

settings.py の変更したとこだけ。

DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'djtest'

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django_evolution',
    'guestbook',
)

とりあえず、これで一度、 syndb を。

$ python manage.py syncdb

sqlite> .schema guestbook_guestbook してみると、

CREATE TABLE "guestbook_guestbook" (
    "id" integer NOT NULL PRIMARY KEY,
    "name" varchar(20) NOT NULL,
    "comment" text NOT NULL,
    "posted_date" datetime NOT NULL
);

guestbook/models.py をちょっと書きかえました。tags と is_public の追加です。リレーションとかするとちょっとめんどそうなので、とりあえずあたりさわりなさそうな感じで。ちなみに必須フィールドは初期値を入れておかないとうまくいきません。この辺のことは次回調べてみようかと。

from django.db import models

class GuestBook(models.Model):
    name = models.CharField(max_length=20)
    tags = models.CommaSeparatedIntegerField(max_length=255, blank=True)
    comment = models.TextField()
    is_public = models.BooleanField(default=True)
    posted_date = models.DateTimeField()

    class Meta:
        pass

    def __unicode__(self):
        return self.name

ちなみに現在、以下のようなデータを入れてあります。

sqlite> select * from guestbook_guestbook;
test|2008-10-13 14:46:31.744999|1|hfunai

これで、

$ python manage.py evolve --hint --execute

yes と答えると、データベースに反映されます。以下のようにデータは無事に残っています。まあこれくらい簡単なのならね…

sqlite> select * from guestbook_guestbook;
test|2008-10-13 14:46:31.744999|1|hfunai||1

とりあえず、面白そうなのでいろいろと試してみますかね。

個人的に、 Django で開発するときは、いきなり Model にかきまくって、どんどん変更していくような開発をしているので、大変便利なのではないかと思ってます。というか使います。

Posted at: 
2008/10/14 05:17:19
0 Comments
1 TrackBack
Tags: 
Django
Trackback: 
http://blog.monospace.jp/2008/10/14/django_evolution/trackback/

Django でファイルアップロード先を動的に変更する方法

Django1.0発表目前ということで、いろいろと最近のアップデートを確認してたんですが、ひそかに待ちこれがれていた、動的にファイルアップロード先を変更することができるようになっていました。

何がしたかったのかというと、ファイルのアップロード先を1つのディレクトリにしてしまうと、大量になった場合に事件が起こるので、それをユーザ名でディレクトリを分けて、比較的平穏にしようというわけです。

今までは、FileField を継承したカスタムフィールド使ってたんですが、File storage refactoring によって upload_to に callable なものが渡せるようになったので、これを使って動的にディレクトリを分けることができるようになりました。ちなみに、日付ベースでディレクトリを分けるっていうのは前からできてたんですよね。個人的には、ユーザごとに分けたいことが多かったのでそっちはあんまり使ったことないです。

def _get_upload_path(instance, filename):
    # ユーザ名をディレクトリに指定
    path = 'store/%s' % instance.user.username
    # ファイル名も自前でつける
    root, ext = os.path.splitext(filename)
    new_root = datetime.now().strftime('%Y%m%d%H%M%S')
    return os.path.join(path, new_root + ext)


class Photo(models.Model):
    user = models.ForeignKey(User)
    title = models.CharField(max_length=255)
    description = models.TextField()
    content = models.FileField(upload_to=_get_upload_path)

アップロード先のパスを返す関数(ここでは、_get_upload_path)を定義しておいて、upload_to に指定するだけです。引数に、 instance (この場合、Photo クラスのインスタンス)と filename を受け取る必要があります。ユーザ名で分ける以外にもいろいろできると思います。アップロード先のパスがない場合も多分作ってくれます。(もちろんパーミッションがあれば)。ドキュメントには、絶対パスを返せって書いてあった気がして、そうしてたら DB にフルパスがはいってしまって困ったりしましたが、通常通り、MEDIA_ROOT 以下のパスだけ渡したら解決しました。

File storage refactoring は他にもいろいろと変わってます。

http://code.djangoproject.com/wiki/FileStorageRefactor

ちなみに、こちらにも同じような内容が書かれていました。

http://scottbarnham.com/blog/2008/08/25/dynamic-upload-paths-in-django/

日本だと今日の深夜あたりにリリースされるんですかね。 Django1.0 楽しみです。

ちなみに今回から reStructuredText でエントリーを書くことにしました。こっちの方が楽。(今までは HTML かいてました)

Posted at: 
2008/09/02 18:56:33
0 Comments
1 TrackBack
Tags: 
Django
Trackback: 
http://blog.monospace.jp/2008/09/02/django_dynamic_upload_path/trackback/

絶対衝激 ~プラトニックハート~ ポータルサイトがオープンしました(ちょっと制作しました)

本日2008年7月7日12:00に、絶対衝激 ~プラトニックハート~ ポータルサイトがオープンしました。
6月上旬からカウントダウンが始まり、謎な感じで展開していたんですが、この度晴れてグランドオープンです。
10社の企業によるコラボレーションで、すでに各種メディアでの展開が決まっていたりして、結構大規模なプロジェクトなのです。

http://zettai.jp/

と、まあ宣伝なのですが、このサイトの制作をお手伝いさせてもらったので紹介です。
Flash がメインのサイトなんですが、弊社が担当したのはバックエンドで、 ActionScript は1行も書いていません。
Flash に関しては、最近 AS 界で話題の Progression Frameworkを使用しています。
サイト構築には、すごくすごく便利といううわさです。(ごめんなさい、ぼくはまだ使ったことないです)
特にパーマリンク的なものを作ってくれるのが非常にいいなーとおもいました。「戻る」ボタン使えるし。

ちなみにバックエンドは、Djangoです。わがまま言って使わせてもらいました。
Flash との連携がかなりの箇所で必要となったわけですが、 Django は非常に柔軟に対応できるので助かりました。
特に、 memcached が簡単にあつかえるのは、すごーく助かりました。実は、アクセス数がかなりのものなので…

そうそう、 Django といえば、日本の優秀な Django ユーザさまによる本が出たばっかですよ。
Django 本はこれだけ持ってればきっとオッケーです。

開発のプロが教える 標準Django完全解説

で、Django の宣伝なのかなんなのかわからなくなってきましたが、ブログパーツ貼ってみました。貼ってるとポイントもらえます。
さわったりすると、音が出るのでご注意を。で、ポイントたまるとどうなるのか。 続きはWEBで。

Posted at: 
2008/07/07 22:43:21
2 Comments
1 TrackBack
Tags: 
Django
works
Trackback: 
http://blog.monospace.jp/2008/07/07/zettai_shogeki/trackback/

Django の管理画面で特定のモデルの特定のフィールドのtextareaだけcolsやrowsを変えたい

つまるところ Django の管理画面の textarea は結構ちっちゃめに設定されてます。
しかもそれを変更するのは、案外というかかなり大変なことになるようで困りました。
ちなみに Safari3 からは、textarea をリサイズする機能が備わっているため困らないでしょう。

ちょっと別な話ですが、特定のアプリの特定のクラスだけリスト表示、詳細表示を変更したいっていうのは簡単です。
例えば、 poll というアプリの Poll クラスだけ詳細・変更フォームを変更したい場合は、
TEMPLATE_DIR 内に admin/poll/poll/ というディレクトリを作成して、その中に、
/usr/lib/python2.5/site-packages/django/contrib/admin/templates/admin あたりにあるchange_form.htmlをコピーします。
んで、それを変更すると、 poll クラスの詳細・変更フォームだけを変更することができます。

今回のケースだとこれだけでは不十分です。
ソースを追いかけていくと、最終的に、django/oldforms/__init__.py の各クラスが render というメソッドを持っていて、
そこで html を生成しています。要するにお手上げですw

結果として、たどり着いたのは Javascript です。(個人的には最終手段だとおもってますが)
Django のソースも HTML も 1 行も書き換えることなく(それはうそですね。下に書いたコード追加しないとだめです。)変更できます。
今回、 Google の AJAX Libraries API を使って jquery を読み込んでみました。

<script src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
<!--
google.load("jquery", "1.2.6");
google.setOnLoadCallback(function(){
    $('input[@type=text]').attr('size', 100);
    $('textarea').attr('rows', 30);
    $('textarea').attr('cols', 120);
});
//-->
</script>

これを、さっきの change_form.html に書けば完了です。とりあえず、input type="text" と textarea を拡張してみました。

とりあえず現状だとこれが一番楽そうなんだけど、 newforms admin ではどうなんだろうか。その辺はまた調べてみます

Posted at: 
2008/07/02 03:40:45
2 Comments
0 TrackBacks
Tags: 
Django
Trackback: 
http://blog.monospace.jp/2008/07/02/django_admin_modify_widget/trackback/