2016年2月14日日曜日

Django1.8 と Celery3.1.20 で、DBに非同期書き込み

やりたいことはタイトルの通りだけど、Webの情報に翻弄され、中々ゴールに辿りつけず。
忘れない内に、メモメモ。

環境
Ubuntu14
RabbitMQ
Django1.8
Celery3.1.20

1.RabbitMQ インストール

$ sudo apt-get install rabbitmq-server

2.Django インストール

$ cd
$ virtualenv env
$ source ~/env/bin/activate
$ pip install --upgrade pip
$ pip install Django==1.8 celery==3.1.20
$ pip freeze
$ cd env

3.アプリケーション

$ django-admin.py startproject proj
$ cd proj
$ python manage.py startapp app1

〜 中略 〜 ※本論では無いので、一旦省略(^^;

4.Django で Celery を使えるようにする。

マニュアルは、こちら
http://docs.celeryproject.org/en/latest/django/index.html

4-1.ファイル構成

proj/
├manage.py
├proj/
│├__init__.py  # 4.3参照
│├settings.py
│├celery.py    # 4.2参照
│└urls.py
└app1/
 ├admin.py
 ├models.py
 ├views.py     # 6参照
 └tasks.py     # 5参照

4-2.Celery インスタンスを定義

File: proj/proj/celery.py
--
from __future__ import absolute_import
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings')
from django.conf import settings
app = Celery('proj')
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
--

4-3.Django 起動時にインスタンスをロード

File: proj/proj/__init__.py
--
from __future__ import absolute_import
from .celery import app as celery_app
--

5.非同期にDBに書き込むタスクを定義

File: proj/app1/tasks.py
--
from __future__ import absolute_import
from celery import shared_task
from .models import Word

@shared_task
def put_word(word):
 w, c = Word.objects.get_or_create(word=word)
 return "ok"
--

# models.py の説明は省略してます。

6.Vewからタスクに渡す

File: proj/app1/views.py
--
from .tasks import put_word

def test(request):
 word = "xxxxxxxx"
 put_word(word)
 return HttpResponse("ok")
--

# urls.py の説明は省略しています。

7.開発サーバを起動して、動作確認

$ celery -A proj worker -l info
$ python manage.py runserver

8.まとめ

Google App Engine では標準で使える機能を、自前で実装できました。
データベースへの書き込みは、レスポンスへの影響が大きい為、できる限り非同期で実行させたいもの。
日本語の情報も少なく、少し苦労したので、どなたかの参考になれば、幸いです。