(16:30 ~ 16:50) 백경준 - 아직도 보고서를 직접 보내시나요?(Feat.Django-celery-beat)
실습을 해보기 전에 공식 문서의 내용을 꼭 읽어보세요!
- python 3.8.2
- Redis server 5.0.5
amqp==2.6.0
asgiref==3.2.7
billiard==3.6.3.0
celery==4.4.5
Django==3.0.7
django-celery-beat==2.0.0
django-timezone-field==4.0
future==0.18.2
kombu==4.6.10
python-crontab==2.5.1
pytz==2020.1
redis==3.5.3
sqlparse==0.3.1
vine==1.3.0
$ python -m venv venv
$ source venv/bin/activate
$ source venv\Scripts\activate.bat
(venv) $ pip install -r requirements.txt
(venv) $ python manage.py migrate
(venv) $ python manage.py runserver
(venv) $ celery worker -A config -P --loglevel=INFO
(venv) $ celery beat -A config --loglevel=INFO
일회성 작업은 clocked schedule을 쓰면 더 편할 것 같아요!.
Periodic_task에 등록할 때
one_off=True 옵션을 꼭 줘야합니다!
주지 않으면 assign 에러가 납니다.
clocked_time = models.DateTimeField(
verbose_name=_('Clock Time'),
help_text=_('Run the task at clocked time'),
)
enabled = models.BooleanField(
default=True,
editable=False,
verbose_name=_('Enabled'),
help_text=_('Set to False to disable the schedule'),
)
Priodic_task의 모델이자 옵션입니다.
name = models.CharField(
max_length=200, unique=True,
verbose_name=_('Name'),
help_text=_('Short Description For This Task'),
)
task = models.CharField(
max_length=200,
verbose_name='Task Name',
help_text=_('The Name of the Celery Task that Should be Run. '
'(Example: "proj.tasks.import_contacts")'),
)
# You can only set ONE of the following schedule FK's
# TODO: Redo this as a GenericForeignKey
interval = models.ForeignKey(
IntervalSchedule, on_delete=models.CASCADE,
null=True, blank=True, verbose_name=_('Interval Schedule'),
help_text=_('Interval Schedule to run the task on. '
'Set only one schedule type, leave the others null.'),
)
crontab = models.ForeignKey(
CrontabSchedule, on_delete=models.CASCADE, null=True, blank=True,
verbose_name=_('Crontab Schedule'),
help_text=_('Crontab Schedule to run the task on. '
'Set only one schedule type, leave the others null.'),
)
solar = models.ForeignKey(
SolarSchedule, on_delete=models.CASCADE, null=True, blank=True,
verbose_name=_('Solar Schedule'),
help_text=_('Solar Schedule to run the task on. '
'Set only one schedule type, leave the others null.'),
)
clocked = models.ForeignKey(
ClockedSchedule, on_delete=models.CASCADE, null=True, blank=True,
verbose_name=_('Clocked Schedule'),
help_text=_('Clocked Schedule to run the task on. '
'Set only one schedule type, leave the others null.'),
)
# TODO: use django's JsonField
args = models.TextField(
blank=True, default='[]',
verbose_name=_('Positional Arguments'),
help_text=_(
'JSON encoded positional arguments '
'(Example: ["arg1", "arg2"])'),
)
kwargs = models.TextField(
blank=True, default='{}',
verbose_name=_('Keyword Arguments'),
help_text=_(
'JSON encoded keyword arguments '
'(Example: {"argument": "value"})'),
)
queue = models.CharField(
max_length=200, blank=True, null=True, default=None,
verbose_name=_('Queue Override'),
help_text=_(
'Queue defined in CELERY_TASK_QUEUES. '
'Leave None for default queuing.'),
)
# you can use low-level AMQP routing options here,
# but you almost certaily want to leave these as None
# http://docs.celeryproject.org/en/latest/userguide/routing.html#exchanges-queues-and-routing-keys
exchange = models.CharField(
max_length=200, blank=True, null=True, default=None,
verbose_name=_('Exchange'),
help_text=_('Override Exchange for low-level AMQP routing'),
)
routing_key = models.CharField(
max_length=200, blank=True, null=True, default=None,
verbose_name=_('Routing Key'),
help_text=_('Override Routing Key for low-level AMQP routing'),
)
headers = models.TextField(
blank=True, default='{}',
verbose_name=_('AMQP Message Headers'),
help_text=_('JSON encoded message headers for the AMQP message.'),
)
priority = models.PositiveIntegerField(
default=None, validators=[MaxValueValidator(255)],
blank=True, null=True,
verbose_name=_('Priority'),
help_text=_(
'Priority Number between 0 and 255. '
'Supported by: RabbitMQ, Redis (priority reversed, 0 is highest).')
)
expires = models.DateTimeField(
blank=True, null=True,
verbose_name=_('Expires Datetime'),
help_text=_(
'Datetime after which the schedule will no longer '
'trigger the task to run'),
)
expire_seconds = models.PositiveIntegerField(
blank=True, null=True,
verbose_name=_('Expires timedelta with seconds'),
help_text=_(
'Timedelta with seconds which the schedule will no longer '
'trigger the task to run'),
)
one_off = models.BooleanField(
default=False,
verbose_name=_('One-off Task'),
help_text=_(
'If True, the schedule will only run the task a single time'),
)
start_time = models.DateTimeField(
blank=True, null=True,
verbose_name=_('Start Datetime'),
help_text=_(
'Datetime when the schedule should begin '
'triggering the task to run'),
)
enabled = models.BooleanField(
default=True,
verbose_name=_('Enabled'),
help_text=_('Set to False to disable the schedule'),
)
last_run_at = models.DateTimeField(
auto_now=False, auto_now_add=False,
editable=False, blank=True, null=True,
verbose_name=_('Last Run Datetime'),
help_text=_(
'Datetime that the schedule last triggered the task to run. '
'Reset to None if enabled is set to False.'),
)
total_run_count = models.PositiveIntegerField(
default=0, editable=False,
verbose_name=_('Total Run Count'),
help_text=_(
'Running count of how many times the schedule '
'has triggered the task'),
)
date_changed = models.DateTimeField(
auto_now=True,
verbose_name=_('Last Modified'),
help_text=_('Datetime that this PeriodicTask was last modified'),
)
description = models.TextField(
blank=True,
verbose_name=_('Description'),
help_text=_(
'Detailed description about the details of this Periodic Task'),
)
Periodic_task의 추가, 수정, 삭제 변경사항을 기록하는 모델입니다.
ident = models.SmallIntegerField(default=1, primary_key=True, unique=True)
last_update = models.DateTimeField(null=False)
crontabSchedule의 옵션이자 데이터베이스 모델입니다. 고정 시간으로 스케줄링합니다.
ex)
minute = models.CharField(
max_length=60 * 4, default='*',
verbose_name=_('Minute(s)'),
help_text=_(
'Cron Minutes to Run. Use "*" for "all". (Example: "0,30")'),
validators=[validators.minute_validator],
)
hour = models.CharField(
max_length=24 * 4, default='*',
verbose_name=_('Hour(s)'),
help_text=_(
'Cron Hours to Run. Use "*" for "all". (Example: "8,20")'),
validators=[validators.hour_validator],
)
day_of_week = models.CharField(
max_length=64, default='*',
verbose_name=_('Day(s) Of The Week'),
help_text=_(
'Cron Days Of The Week to Run. Use "*" for "all". '
'(Example: "0,5")'),
validators=[validators.day_of_week_validator],
)
day_of_month = models.CharField(
max_length=31 * 4, default='*',
verbose_name=_('Day(s) Of The Month'),
help_text=_(
'Cron Days Of The Month to Run. Use "*" for "all". '
'(Example: "1,15")'),
validators=[validators.day_of_month_validator],
)
month_of_year = models.CharField(
max_length=64, default='*',
verbose_name=_('Month(s) Of The Year'),
help_text=_(
'Cron Months Of The Year to Run. Use "*" for "all". '
'(Example: "0,6")'),
validators=[validators.month_of_year_validator],
)
timezone = timezone_field.TimeZoneField(
default='UTC',
verbose_name=_('Cron Timezone'),
help_text=_(
'Timezone to Run the Cron Schedule on. Default is UTC.'),
)
intervalschedule의 옵션이자 데이터베이스 모델입니다.상대 시간으로 스케줄링합니다.
every = models.IntegerField(
null=False,
verbose_name=_('Number of Periods'),
help_text=_('Number of interval periods to wait before '
'running the task again'),
validators=[MinValueValidator(1)],
)
period = models.CharField(
max_length=24, choices=PERIOD_CHOICES,
verbose_name=_('Interval Period'),
help_text=_('The type of period between task runs (Example: days)'),
)
- IntervalSchedule.DAYS
- IntervalSchedule.HOURS
- IntervalSchedule.MINUTES
- IntervalSchedule.SECONDS
- IntervalSchedule.MICROSECONDS
경도와 위도로 위치를 정하고, 그 위치에서 해의 움직임에 대한 이벤트로 동작합니다
event = models.CharField(
max_length=24, choices=SOLAR_SCHEDULES,
verbose_name=_('Solar Event'),
help_text=_('The type of solar event when the job should run'),
)
latitude = models.DecimalField(
max_digits=9, decimal_places=6,
verbose_name=_('Latitude'),
help_text=_('Run the task when the event happens at this latitude'),
validators=[MinValueValidator(-90), MaxValueValidator(90)],
)
longitude = models.DecimalField(
max_digits=9, decimal_places=6,
verbose_name=_('Longitude'),
help_text=_('Run the task when the event happens at this longitude'),
validators=[MinValueValidator(-180), MaxValueValidator(180)],
)
태양 위치에 따라 이벤트가 실행됩니다.
- sunset : 일몰, solar_noon : 정오(태양의 고도 = 90°), sunrise : 일출
- dawn_civil, dawn_nautical, dawn_astronomical
- dusk_civil, dusk_nautical, dusk_astronomical