2013年2月3日日曜日

Django "sites"フレームワーク を使う

Django のマニュアルによると、1つのインスタンスで複数のサイトを運営できるようなことが書いてある。
http://docs.djangoproject.jp/en/latest/ref/contrib/sites.html#ref-contrib-sites

でも、そもそも、複数のサイトを切り替える手順が、どこにも書いてないんだよね??
ググっても、日本語の情報は無し。

英語のサイトを眺めながら、なんとなく、使えそうな方法を見つけた。

以下は、その手順

1.ミドルウェアの追加

settings.py の MIDDLEWARE_CLASSES に、ミドルウェア(後述)を追加

-- settings.py --
MIDDLEWARE_CLASSES = (
 'mysite.middle.MultiSiteMiddleware',

補足
mysite : プロジェクトのフォルダ名
middle : ファイル名(meddle.py)
MultiSiteMiddleware : クラス名

2.ミドルウェアを書く

アクセスされたドメイン名に対応するサイトID を設定します。

-- mysite.middle.py --
from django.conf import settings
from django.contrib.sites.models import Site
class MultiSiteMiddleware:  
 def process_request(self, request):
  host = request.get_host()
  try:
   site = Site.objects.get(domain=host)
  except Site.DoesNotExist:
   site = Site(domain=host, name=host)
   site.save()
  settings.SITE_ID = site.id

概要
・request.get_host() で、外部からアクセスされたドメイン名(host)を取り出し
・site オブジェクトを get (または、save)
・サイトID(site.id) を、SITE_ID にセット

ミドルウェアが、どのように動作するかは、こちらを参考に。
http://docs.djangoproject.jp/en/latest/topics/http/middleware.html

3.SITE_ID を使う

SITE_ID を get できれば、後は、ドキュメント通りにイロイロ応用できます。


-- views.py --
from django.conf import settings
from django.contrib.sites.models import Site
sid = settings.SITE_ID
site = Site.objects.get(id=sid)
# site.id, site.domain, site.name

余談ですが..
"sites"フレームワーク を使えば、ドメイン毎に、Apache の バーチャルホストを設定する必要はありません。


2013/02/17 追記

settings.SITE_ID = site.id では、SITE_ID をキチンとセットできないみたい。

さらに、ググってみると、こちらを見つけた。

http://djangosnippets.org/snippets/1099/

1.設定ファイル

-- settings.py --
from site_id_hook import SiteIDHook, SITE_THREAD_INFO
SITE_ID = SiteIDHook()

MIDDLEWARE_CLASSES = (
 'mysite.site_middleware.SiteOnFlyDetectionMiddleware',
 …
)

※ site_middleware は、MIDDLEWARE_CLASSES の先頭に記述します。

2.SITE_ID 取得

-- site_id_hook.py --
from threading import local
SITE_THREAD_INFO = local()
class SiteIDHook:
 def __int__(self):      
  return SITE_THREAD_INFO.SITE_ID
 def __hash__(self):      
  return SITE_THREAD_INFO.SITE_ID

3.ミドルウェア

-- site_middleware.py --
from django.conf import settings
from django.contrib.sites.models import Site
class SiteOnFlyDetectionMiddleware:  
 def process_request(self, request):
  host = request.get_host()
  try:
   site = Site.objects.get(domain=host)
  except Site.DoesNotExist:
   site = Site(domain=host, name=host)
   site.save()
  settings.SITE_THREAD_INFO.SITE_ID = site.id

今渡こそ、大丈夫かな??

0 件のコメント:

コメントを投稿