Django+Celery实现定时任务的示例


Posted in Python onJune 23, 2021
目录
  • 一、前言
  • 二、配置使用
  • 定义与触发任务
  • 扩展
  • 三、Django中使用定时任务
  • 二次开发

 

一、前言

  Celery是一个基于python开发的分布式任务队列,而做python WEB开发最为流行的框架莫属Django,但是Django的请求处理过程都是同步的无法实现异步任务,若要实现异步任务处理需要通过其他方式(前端的一般解决方案是ajax操作),而后台Celery就是不错的选择。倘若一个用户在执行某些操作需要等待很久才返回,这大大降低了网站的吞吐量。

​另一方面,当我们需要处理一些定时任务时Celery强大的生态环境也是他的优势。

​在刚刚学习如何使用Celery时可能会觉得难以入手,我利用工作之余研究这些文档前前后后也花了快一个周的样子,目前已经可以满足我的需求,所以静下心多写多测试,加油。

Django+Celery实现定时任务的示例

 

二、配置使用

  celery很容易集成到Django框架中,当然如果想要实现定时任务的话还需要安装django-celery-beta插件,后面会说明。需要注意的是Celery4.0只支持Django版本>=1.8的,如果是小于1.8版本需要使用Celery3.1。

本示例使用主要依赖包如下:

celery==4.2.1
Django==1.11.7
django-celery-beat==1.4.0
django-celery-results==1.0.4
PyMySQL==0.9.2
redis==2.10.6

配置

  新建立项目celery_demo,目录结构(每个app下多了个tasks文件,用于定义任务):

celery_demo
├── app01
│   ├── __init__.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tasks.py
│   └── views.py
├── manage.py
├── celery_demo
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── templates

在项目目录celery_demo/celery_demo/目录下新建celery.py:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author:wd
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery

# 设置django环境
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'celery_demo.settings')  
app = Celery('celery_demo')
#  使用CELERY_ 作为前缀,在settings中写配置
app.config_from_object('django.conf:settings', namespace='CELERY') 
# 发现任务文件每个app下的task.py
app.autodiscover_tasks()

celery_demo/celery_demo/__init__.py写入:

from __future__ import absolute_import, unicode_literals
from .celery import app as celery_app
__all__ = ['celery_app']

celery_demo/celery_demo/settings.py写入:

CELERY_BROKER_URL = 'redis://10.1.210.69:6379/0' # Broker配置,使用Redis作为消息中间件

CELERY_RESULT_BACKEND = 'redis://10.1.210.69:6379/0' # BACKEND配置,这里使用redis

CELERY_RESULT_SERIALIZER = 'json' # 结果序列化方案

进入项目的celery_demo目录启动worker

celery worker -A taskproj -l debug

 

定义与触发任务

任务定义在每个tasks文件中,app01/tasks.py

from __future__ import absolute_import, unicode_literals
from celery import shared_task
@shared_task
def add(x, y):
    return x + y
@shared_task
def mul(x, y):
    return x * y

视图中触发任务

from django.http import JsonResponse
from app01 import tasks

# Create your views here.

def index(request,*args,**kwargs):
    res=tasks.add.delay(1,3)
    #任务逻辑
    return JsonResponse({'status':'successful','task_id':res.task_id})

访问http://127.0.0.1:8000/index

Django+Celery实现定时任务的示例

若想获取任务结果,可以通过task_id使用AsyncResult获取结果,还可以直接通过backend获取:

Django+Celery实现定时任务的示例

 

扩展

  除了redis、rabbitmq能做结果存储外,还可以使用Django的orm作为结果存储,当然需要安装依赖插件,这样的好处在于我们可以直接通过django的数据查看到任务状态,同时为可以制定更多的操作,下面介绍如何使用orm作为结果存储。

安装

pip install django-celery-results

配置settings.py,注册app

INSTALLED_APPS = (
    ...,
    'django_celery_results',
)

修改backend配置,将Redis改为django-db

#CELERY_RESULT_BACKEND = 'redis://10.1.210.69:6379/0' # BACKEND配置,这里使用redis

CELERY_RESULT_BACKEND = 'django-db'  #使用django orm 作为结果存储

修改数据库

python3 manage.py migrate django_celery_results

此时会看到数据库会多创建:

Django+Celery实现定时任务的示例 

当然你有时候需要对task表进行操作,以下源码的表结构定义:

class TaskResult(models.Model):
    """Task result/status."""

    task_id = models.CharField(_('task id'), max_length=255, unique=True)
    task_name = models.CharField(_('task name'), null=True, max_length=255)
    task_args = models.TextField(_('task arguments'), null=True)
    task_kwargs = models.TextField(_('task kwargs'), null=True)
    status = models.CharField(_('state'), max_length=50,
                              default=states.PENDING,
                              choices=TASK_STATE_CHOICES
                              )
    content_type = models.CharField(_('content type'), max_length=128)
    content_encoding = models.CharField(_('content encoding'), max_length=64)
    result = models.TextField(null=True, default=None, editable=False)
    date_done = models.DateTimeField(_('done at'), auto_now=True)
    traceback = models.TextField(_('traceback'), blank=True, null=True)
    hidden = models.BooleanField(editable=False, default=False, db_index=True)
    meta = models.TextField(null=True, default=None, editable=False)

    objects = managers.TaskResultManager()

    class Meta:
        """Table information."""

        ordering = ['-date_done']

        verbose_name = _('task result')
        verbose_name_plural = _('task results')

    def as_dict(self):
        return {
            'task_id': self.task_id,
            'task_name': self.task_name,
            'task_args': self.task_args,
            'task_kwargs': self.task_kwargs,
            'status': self.status,
            'result': self.result,
            'date_done': self.date_done,
            'traceback': self.traceback,
            'meta': self.meta,
        }

    def __str__(self):
        return '<Task: {0.task_id} ({0.status})>'.format(self)

 

三、Django中使用定时任务

  如果想要在django中使用定时任务功能同样是靠beat完成任务发送功能,当在Django中使用定时任务时,需要安装django-celery-beat插件。以下将介绍使用过程。

安装配置

1.beat插件安装

pip3 install django-celery-beat

2.注册APP

INSTALLED_APPS = [
    ....   
    'django_celery_beat',
]

3.数据库变更

python3 manage.py migrate django_celery_beat

4.分别启动woker和beta

celery -A proj beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler  #启动beta 调度器使用数据库

celery worker -A taskproj -l info #启动woker

5.配置admin

urls.py写入:

# urls.py
from django.conf.urls import url
from django.contrib import admin
 
urlpatterns = [
    url(r'^admin/', admin.site.urls),
]

6.创建用户

python3 manage.py createsuperuser

7.登录admin进行管理(地址http://127.0.0.1:8000/admin)并且还可以看到我们上次使用orm作为结果存储的表。

http://127.0.0.1:8000/admin/login/?next=/admin/

Django+Celery实现定时任务的示例

使用示例:

Django+Celery实现定时任务的示例

Django+Celery实现定时任务的示例

查看结果:

Django+Celery实现定时任务的示例

 

二次开发

  django-celery-beat插件本质上是对数据库表变化检查,一旦有数据库表改变,调度器重新读取任务进行调度,所以如果想自己定制的任务页面,只需要操作beat插件的四张表就可以了。当然你还可以自己定义调度器,django-celery-beat插件已经内置了model,只需要进行导入便可进行orm操作,以下我用django reset api进行示例:

settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    'django_celery_results',
    'django_celery_beat',
    'rest_framework',
]

urls.py

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index$', views.index),
    url(r'^res$', views.get_res),
    url(r'^tasks$', views.TaskView.as_view({'get':'list'})),
]

views.py

from django_celery_beat.models import PeriodicTask  #倒入插件model
from rest_framework import serializers
from rest_framework import pagination
from rest_framework.viewsets import ModelViewSet
class Userserializer(serializers.ModelSerializer):
    class Meta:
        model = PeriodicTask
        fields = '__all__'

class Mypagination(pagination.PageNumberPagination):
    """自定义分页"""
    page_size=2
    page_query_param = 'p'
    page_size_query_param='size'
    max_page_size=4

class TaskView(ModelViewSet):
    queryset = PeriodicTask.objects.all()
    serializer_class = Userserializer
    permission_classes = []
    pagination_class = Mypagination

访问http://127.0.0.1:8000/tasks如下:

Django+Celery实现定时任务的示例

参考资料:

W-D:https://www.cnblogs.com/wdliu/p/9530219.html

还在琢磨:https://blog.csdn.net/mbl114/article/details/78047175

Celery文档:http://docs.celeryproject.org/en/latest/

以上就是Django+Celery实现定时任务的示例的详细内容,更多关于Django Celery定时任务的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python入门篇之函数
Oct 20 Python
使用python实现正则匹配检索远端FTP目录下的文件
Mar 25 Python
python脚本监控docker容器
Apr 27 Python
详解duck typing鸭子类型程序设计与Python的实现示例
Jun 03 Python
Python实现视频下载功能
Mar 14 Python
python爬虫获取京东手机图片的图文教程
Dec 29 Python
python实战之实现excel读取、统计、写入的示例讲解
May 02 Python
python使用folium库绘制地图点击框
Sep 21 Python
使用python去除图片白色像素的实例
Dec 12 Python
Tensorflow不支持AVX2指令集的解决方法
Feb 03 Python
CentOS 7如何实现定时执行python脚本
Jun 24 Python
利用For循环遍历Python字典的三种方法实例
Mar 25 Python
Python django中如何使用restful框架
Python基础之变量的相关知识总结
Jun 23 #Python
浅谈Python数学建模之固定费用问题
浅谈Python数学建模之整数规划
浅谈Python数学建模之数据导入
Jun 23 #Python
python四种出行路线规划的实现
浅谈Python数学建模之线性规划
Jun 23 #Python
You might like
php 方便水印和缩略图的图形类
2009/05/21 PHP
解析CodeIgniter自定义配置文件
2013/06/18 PHP
PHP随机生成信用卡卡号的方法
2015/03/23 PHP
基于laravel制作APP接口(API)
2016/03/15 PHP
php实现替换手机号中间数字为*号及隐藏IP最后几位的方法
2016/11/16 PHP
JS+PHP实现用户输入数字后显示最大的值及所在位置
2017/06/19 PHP
jquery 新浪网易的评论块制作
2010/07/01 Javascript
JavaScript中:表达式和语句的区别[译]
2012/09/17 Javascript
键盘上一张下一张兼容IE/google/firefox等浏览器
2014/01/28 Javascript
JavaScript显示当前文档最后修改日期的方法
2015/03/19 Javascript
JS延时提示框实现方法详解
2015/11/26 Javascript
Angular ng-repeat遍历渲染完页面后执行其他操作详细介绍
2016/12/13 Javascript
hovertree插件实现二级树形菜单(简单实用)
2016/12/28 Javascript
原生Aajax 和jQuery Ajax 写法个人总结
2017/03/24 jQuery
详解JS获取HTML DOM元素的8种方法
2017/06/17 Javascript
JavaScript 面向对象基础简单示例
2019/10/02 Javascript
vue移动端模态框(可传参)的实现
2019/11/20 Javascript
ES2020系列之空值合并运算符 '??'
2020/07/22 Javascript
[03:49]DOTA2 2015国际邀请赛中国区预选赛第二日现场百态
2015/05/27 DOTA
python进程类subprocess的一些操作方法例子
2014/11/22 Python
Python 实现字符串中指定位置插入一个字符
2018/05/02 Python
python绘制简单彩虹图
2018/11/19 Python
pytorch对可变长度序列的处理方法详解
2018/12/08 Python
python time.sleep()是睡眠线程还是进程
2019/07/09 Python
Python 实用技巧之利用Shell通配符做字符串匹配
2019/08/23 Python
Python pandas.DataFrame 找出有空值的行
2019/09/09 Python
Python3 实现减少可调用对象的参数个数
2019/12/20 Python
Tensorflow实现多GPU并行方式
2020/02/03 Python
Windows下Sqlmap环境安装教程详解
2020/08/04 Python
面试后的感谢信范文
2014/02/01 职场文书
先进集体获奖感言
2014/02/13 职场文书
新学期教师寄语
2014/04/02 职场文书
商场促销活动总结
2014/07/10 职场文书
党校团干班培训心得体会
2016/01/06 职场文书
深度学习小工程练习之垃圾分类详解
2021/04/14 Python
Python时间操作之pytz模块使用详解
2022/06/14 Python