[Django] Apscheduler로 자동으로 데이터 관리

 

apscheduler 를 통해서 특정 날짜에 데이터 갱신하기

 

한 달에 한번씩 유저의 활동 정보를 기록하는 기능이 필요했다.

자동으로 원하는 일을 서버에서 시키는 기능인 apscheduler를 사용했다.

django_apscheduler라는 모듈을 설정하면 쉽게 모든 기능을 사용할 수 있다.

 

 

https://apscheduler.readthedocs.io/en/master/userguide.html#combining-multiple-triggers

 

User guide — APScheduler documentation

Context variables Schedulers provide certain context variables available to the tasks being run: The current (synchronous) scheduler: current_scheduler The current asynchronous scheduler: current_async_scheduler Information about the job being currently ru

apscheduler.readthedocs.io

 

1. 스케줄러 설치 

pip install django-apscheduler

 

2. 스케줄러 관리 파일 생성

 

스케줄러를 생성하면 해당 폴더 내부에 .pyc라는 내부 파일도 함께 생성된다.

이러한 파일들을 한 번에 관리하기 위해서 새로 폴더를 생성했다.

스케줄러 기능을 적용할 앱에 jobs 폴더를 생성한 후 updater.py 파일을 생성한다.

 

3. updater.py 작성

 

스케줄러를 생성하고 적용하는 코드를 작성한다.

내가 실행하고 싶은 스케줄을 작성한다.

sched = BackgroundScheduler()를 생성하고 해당 변수에 save_list() 기능함수를 적용한다.

save_list()는 기존 데이터가 있는지 확인하고, 데이터가 없다면 유저의 레코드를 새로 생성한다.

이 동작은 scheduled_job 함수를 통해서 매달 1일에 실행된다. 

또 해당 레코드를 점수 순으로 정렬해서 랭킹 데이터를 제작한다.

order_by를 통해서 점수가 높은 순부터 정렬한다.

 

sched = BackgroundScheduler()
#테스트
# @sched.scheduled_job('interval',seconds=30,id = "update")
# 매달 1일 실행 
@sched.scheduled_job('interval',days=1,id = "update")
def save_list():
    now = datetime.now() - timedelta(days=1) # 전 날 발급 
    print(now) 
    lastKeyDate = ""
    if now.month<10:
        lastKeyDate = str(now.year)+".0"+str(now.month)
    else:
        lastKeyDate = str(now.year)+"."+str(now.month)
    
    dataList = MonthData.objects.filter(keyDate=lastKeyDate).order_by('-totalPoint')

    # 기존 데이터가 없고 이전 달의 데이터가 있는경우만 실행 
    if not RecordData.objects.filter(keyDate=lastKeyDate) and dataList:
        # 점수 순으로 받기 
        for i in range(0,len(dataList)):
            data = MonthDataSerializer(dataList[i]).data
            print(i+1,data["totalPer"],data["totalPoint"])
            RecordData.objects.create(
                ranking = (i+1),
                userId = dataList[i].userId,
                keyDate = lastKeyDate,
                totalPer = data["totalPer"],
                totalPoint = data["totalPoint"],
                activityNum = data["taskCount"]+data["dayRoutineCount"],
                clearNum = data["doneTask"] + data["clearRoutine"]
            )

 

이 후에 start() 함수를 통해서 스케줄을 실행한다.

def start():
    sched.start()

 

4. app.py 작성

 

서버가 실행되었을 때, Django가 Scheduler를 포함해서 실행하기 위해서는 app.py에 스케줄을 추가해야 한다.

해당 앱의 apps.py파일에 만든 스케줄러를 적용한다 .

 

class MonthreportConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'monthReport'

    def ready(self):
        from .jobs import updater

        if settings.SCHEDULER_DEFAULT: # 한 번만 실행 
            updater.start()

 

ready 함수를 통해서 앱이 실행될 때 작성 된 스케줄러를 실행한다.

settings.SCHEDULER_DEFAULT를 통해서 한 번만 실행하도록 한다.

 

SCHEDULER_DEFAULT = True

 

 

매달 1일 0시에 Scheduler가 동작해서 Month 레코드를 생성한다.

클라이언트에서 지난 달의 유저 랭킹과 활동 정보를 확인할 수 있다.