본문 바로가기

Python/Celery

Python: Celery with Django

728x90
반응형

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 앱 내에서 태스크를 정의할 때  등

728x90
반응형