apscheduler 를 통해서 특정 날짜에 데이터 갱신하기
한 달에 한번씩 유저의 활동 정보를 기록하는 기능이 필요했다.
자동으로 원하는 일을 서버에서 시키는 기능인 apscheduler를 사용했다.
django_apscheduler라는 모듈을 설정하면 쉽게 모든 기능을 사용할 수 있다.
https://apscheduler.readthedocs.io/en/master/userguide.html#combining-multiple-triggers
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 레코드를 생성한다.
클라이언트에서 지난 달의 유저 랭킹과 활동 정보를 확인할 수 있다.