読者です 読者をやめる 読者になる 読者になる

Mobile on Django

Django

Djangoで携帯向けサイトを構築するためのプラグイン。
まだ、構想段階なので、以下はメモ。
名前はプロジェクト名をdjango-mobilejpにして、モジュール名をmobilejpにしようかな。

インストール

$ easy_install django-mobilejp

でインストールできるようにする。
Django 0.97以上を必須とする予定。

モジュール構成(予定)

mobilejp.templatetags
Djangoテンプレートで絵文字や携帯向けHTMLを出力するのを支援するテンプレートタグ
mobilejp.mail
各キャリアごとのメール送信処理
mobilejp.forms
絵文字入りのフォームデータを扱うためのnewformsラッパーライブラリ
mobilejp.emoji
絵文字をエンコード・デコードするためのライブラリ
mobilejp.middleware
Djangoミドルウェア。ユーザエージェント、IPの判別等。

使用法

DEFAULT_CHARSET

settings.DEFAULT_CHARSETはcp932を指定することが必須。

# settings.py

DEFAULT_CHARSET='cp932'

一方、settings.FILE_CHARSETは何を選んでもよい。デフォルトでは、Djangoの標準のutf8。
テンプレートをShift_JISで書きたい場合は、'Shift_JIS', 'cp932'等にする。

# settings.py

FILE_CHARSET='cp932'
ミドルウェアに登録する

mobilejp.middleware.UserAgentMobileMiddlewareを有効にする。テンプレートタグやフォームの処理で、このミドルウェアのThreadLocalオブジェクトを参照しているので、この設定は必須。

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'mobilejp.middleware.UserAgentMobileMiddleware',
    'mobilejp.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.doc.XViewMiddleware',
)

セッションを利用する場合は、Cookieを使えない端末の対策として、mobilejp.middleware.SessionMiddlewareを使う必要がある。また、このSessionMiddlewareはUserAgentMobileMiddlewareの後に配置しなくてはならない。

ビューを定義する

ビューは通常通り定義する。フォームを使う場合は、絵文字処理や一部のSoftBank端末のバグ?を回避するため、mobilejp.forms.Formを使うことを推奨。

from django.shortcuts import *
import mobilejp.forms as forms

class MyForm(forms.Form):
    nickname = forms.EmojiField(max_length=50)
    age      = forms.IntegerField()

def default(req):
    form = MyForm(req.POST or None)
    if form.is_valid():
        # Do something
        return render_to_response('accepted.html')

    return render_to_response('form.html')

テンプレート

通常のテンプレート通り記述する。{% load mobile %}で携帯向けの各種テンプレートタグが使用できる。

{% load mobile %}
<html>
<body>
動いているよ{% emoji sun %}
</body>
</html>

{% emoji %}は、ユーザエージェントに合わせて適切なコードを出力する。
リンクはおそらく、次のニ形式のどちらか一方のみをサポートする。

<a href="{% mobile_url path.to.some_view arg1,arg2,name1=value1 %}">リンク</a>
{% link href="/some/path/${object.id}/" %}リンク{% endlink %}

前者はDjangoの{% url %}タグをラップした独自タグで、後者はブロックタグの引数内に変数を埋め込めるように拡張した独自ブロックタグ。両者とも、Cookie非対応端末の場合に、リクエストのパスにセッションIDを埋め込んだURLを返す。

メール関連

from mobilejp.mail import send_mail

send_mail(u'タイトル', u'本文', 'spam@example.com',
    ['spam@docomo.ne.jp'], fail_silently=False)

で送信できるようにする。
アドレスで判断してDoCoMo, auにはShift_JIS, SoftBankにはUTF-8, それ以外にはISO-2022-JPというようにエンコーディングを固定して送信しているけど、どうだろう?
一応今は、force_encoding='ISO-2022-JP'という追加の引数を指定すると、絵文字は下駄に置き換えて、指定したエンコーディングで送信できるようになっている。

開発版のDjangoのコードをラップして、テスト時に実際にメールを送信しないでもテスト可能にすることが重要。

絵文字関連

今やっている形式でそのまま行くか、Mobile on Rails, Rubyのjpmobileの方式で行くか検討中。

Railsには何で類似プラグインが2つもあるんだろ?

その他, ToDo

  • IPアドレスによる制限の仕方。例外IPアドレスの設定法。
  • 開発時(settings.DEBUG=True)の時、通常のDjangoのエラー画面ではなく、もっと簡潔なエラートレースを返すようにする。
  • クライアントがau端末の場合、エラー時に通常のステータスコードを置き換えて、HTTP 200でエラードキュメントを返すようにする?

やるつもりがないこと

  • QRコード関連。
  • 位置情報, GPS機能。これは今準備中の別ライブラリを使えば、結構快適に扱えるはず。