Django 프로젝트 내에 Celery를 두고 연계해서 사용하기
* Install
redis 설치(ubuntu 기준)
$ sudo apt update
$ sudo apt install redis-server
부팅시 redis 시작
$ sudo systemctl enable redis-server
celery[redis] 설치
$ pip install celery[redis]
* Celery - Django 설정
1. celery.py
Django의 settings.py와 같은 경로에 celery.py 를 생성
(settings/local.py 또는 settings/base.py등, 환경에 따라 나눈 경우 settings 폴더와 같은 경로에 두면 됨)
import os
from celery import Celery
from django.conf import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.local')
app = Celery('config')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
현재 나의 django 프로젝트 파일구성은
project/django_proj/config/settings/local.py 과 같이 되어 있고,
django_proj 경로 내에서 Django를 구동(django_proj/manage.py)
따라서 위와 같이
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.local')로 구성
app.config_from_object('django.conf:settings', namespace='CELERY') -> namespace를 이렇게 정해줬으므로
CELERY로 시작하는 설정들을 인식 (broker_url, result_backend...)
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
-> Django app 안에 tasks.py 파일들이 있을 경우 @app.task 또는 @shared_task가 붙은 함수들을 task에 자동으로 등록한다.
2. settings.py (settings/local.py 등)
REDIS_URL = 'redis://localhost:6379/0'
CELERY_BROKER_URL = REDIS_URL
CELERY_RESULT_BACKEND = REDIS_URL
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'UTC'
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True
3. __init__.py (django_proj/config/__init__.py)
from .celery import app as celery_app
__all__ = ('celery_app',)
* Celery 구동
$ celery -A PROJECT_NAME worker --logvel=info
$ celery -A config worker --loglevel=info
* Celery Task
- shared_task
from celery import shared_task
@shared_task
def my_task(param):
# Your task logic here
pass
또는
- app.task
from config.celery import app
from django.core import serializers
from .models import User
@app.task
def users_task():
return serializers.serialize('json', User.objects.all())
@app.task 에서 실제 예시로 Django ORM을 사용했는데, 해당 결과값은 QuerySet이고
QuerySet은 serailizable 하지 않기 때문에 Celery 단에서 오류 발생
따라서 위와 같이 django 내장 library 등을 사용하여 serialize 후 return
views.py
from django.http import JsonResponse
from .models import Item
from .tasks import items_task
def celery_test(request):
result_item = items_task.delay()
print(result_item)
return JsonResponse({"stauts":"succes"})
views.py 등에서 해당 task를 import 한후 .delay() 등과 같은 형태로 사용
예시 코드 정리
https://github.com/Junanjunan/kshop/commit/3b672fc8c0678f10cabe4f021da9420c13e042fa
@app.task vs @shared_task
주요 차이점
-인스턴스 의존성
@app.task
이 데코레이터는 특정 Celery 앱 인스턴스 (app이라고 표시된)에 종속.
따라서 이 태스크를 정의하는 위치에서 해당 Celery 앱 인스턴스를 알고 있어야 함.
@shared_task
이 데코레이터는 특정 Celery 앱 인스턴스에 종속되지 않음.
이는 재사용 가능한 모듈 또는 앱 내에서 태스크를 정의할 때 유용하며,
해당 태스크를 사용하는 프로젝트에서 어떤 Celery 앱 인스턴스를 사용하든 관계 없이 동일하게 작동
주 사용 사례:
@app.task
주로 해당 앱 또는 프로젝트에서만 사용되는 태스크를 정의할 때 사용
@shared_task
여러 프로젝트에서 재사용하려는 앱이나 모듈 내에서 태스크를 정의할 때 사용.
예를 들어, 여러 Django 프로젝트에서 사용할 수 있는 third-party 앱 내에서 태스크를 정의할 때 등