├── demoapp ├── __init__.py ├── views.py ├── models.py ├── tasks.py └── tests.py ├── dump.rdb ├── celerybeat-schedule ├── proj ├── __init__.py ├── settings_secret.py ├── wsgi.py ├── urls.py ├── celery.py └── settings.py ├── manage.py ├── .gitignore └── README.md /demoapp/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demoapp/views.py: -------------------------------------------------------------------------------- 1 | # Create your views here. -------------------------------------------------------------------------------- /dump.rdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeumus/django-celery-example/HEAD/dump.rdb -------------------------------------------------------------------------------- /demoapp/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models # noqa 2 | 3 | # Create your models here. -------------------------------------------------------------------------------- /celerybeat-schedule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeumus/django-celery-example/HEAD/celerybeat-schedule -------------------------------------------------------------------------------- /proj/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | # This will make sure the app is always imported when 4 | # Django starts so that shared_task will use this app. 5 | from .celery import app as celery_app -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "proj.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /demoapp/tasks.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from celery import shared_task 4 | 5 | 6 | @shared_task 7 | def add(x, y): 8 | return x + y 9 | 10 | 11 | @shared_task 12 | def mul(x, y): 13 | return x * y 14 | 15 | 16 | @shared_task 17 | def xsum(numbers): 18 | return sum(numbers) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .pyc 2 | .c9 3 | *.log 4 | *.pid 5 | *.db 6 | proj/*.log 7 | demoapp/*.log 8 | workspace 9 | dump.rdb 10 | 11 | # a way to hide your django secret key from github see: 12 | # http://fearofcode.github.io/blog/2013/01/15/how-to-scrub-sensitive-information-from-django-settings-dot-py-files/ 13 | # proj/settings_secret.py -------------------------------------------------------------------------------- /proj/settings_secret.py: -------------------------------------------------------------------------------- 1 | # http://fearofcode.github.io/blog/2013/01/15/how-to-scrub-sensitive-information-from-django-settings-dot-py-files/ 2 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 3 | import os 4 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 5 | 6 | # SECURITY WARNING: keep the secret key used in production secret! 7 | SECRET_KEY = 'x2$s&0z2xehpnt_99i8q3)4)t*5q@+n(+6jrqz4@rt%a8fdf+!' -------------------------------------------------------------------------------- /demoapp/tests.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file demonstrates writing tests using the unittest module. These will pass 3 | when you run "manage.py test". 4 | 5 | Replace this with more appropriate tests for your application. 6 | """ 7 | 8 | from django.test import TestCase 9 | 10 | 11 | class SimpleTest(TestCase): 12 | def test_basic_addition(self): 13 | """ 14 | Tests that 1 + 1 always equals 2. 15 | """ 16 | self.assertEqual(1 + 1, 2) -------------------------------------------------------------------------------- /proj/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for celery_django_example project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "celery_django_example.settings") 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | application = get_wsgi_application() 15 | -------------------------------------------------------------------------------- /proj/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, include, url 2 | from django.contrib import admin 3 | 4 | urlpatterns = patterns('', 5 | # Examples: 6 | # url(r'^$', 'celery_django_example.views.home', name='home'), 7 | # url(r'^blog/', include('blog.urls')), 8 | 9 | url(r'^admin/', include(admin.site.urls)), 10 | # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), # https://docs.djangoproject.com/en/1.8/ref/contrib/admin/admindocs/#overview 11 | ) 12 | -------------------------------------------------------------------------------- /proj/celery.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import os 4 | 5 | from celery import Celery 6 | 7 | # set the default Django settings module for the 'celery' program. 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings') 9 | 10 | from django.conf import settings 11 | 12 | app = Celery('proj') 13 | 14 | # Using a string here means the worker will not have to 15 | # pickle the object when using Windows. 16 | app.config_from_object('django.conf:settings') 17 | app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) 18 | 19 | 20 | @app.task(bind=True) 21 | def debug_task(self): 22 | print('Request: {0!r}'.format(self.request)) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Django-Celery Example 2 | ![django admin with django-celery tasks dashboard](https://0839a63ecb79fafd04ced14c58bd0806808b39ce.googledrive.com/host/0B9LVk4xbDIJTYmZXS2p3RVo0OXM) 3 | 4 | ⚠ Warning this was done in Dajngo 1.7 * 5 | _ _ _ 6 | 7 | #### Get Django-Celery Working! 8 | 1. Install [Python](https://www.python.org/downloads/) (if you're in linux, python 2.7 is already installed), [pip](https://pip.pypa.io/en/latest/installing.html), [django](https://docs.djangoproject.com/en/1.8/topics/install/) (and run `./manage.py syncdb`), [celery](http://www.celeryproject.org/install/), and django-celery 9 | 2. Choose your celery broker and install that: [RabbitMQ](http://celery.readthedocs.org/en/latest/getting-started/brokers/rabbitmq.html), [Redis](http://celery.readthedocs.org/en/latest/getting-started/brokers/redis.html), [others...](http://celery.readthedocs.org/en/latest/getting-started/brokers/) 10 | 3. Setup django-celery part 1: http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html#using-the-django-orm-cache-as-a-result-backend 11 | 4. Setup django-celery part 2: https://github.com/celery/django-celery/blob/master/README.rst#using-django-celery 12 | 4. Start all the things (processes): 13 | 4. Start your `redis-server` or `rabbitmq-server`, ect... 14 | 5. Start Django: `./manage.py runserver` (and `./manage.py runserver $IP:$PORT` in Cloud 9) 15 | 6. Start the Celery Event Camera via: `./manage.py celery events --camera=djcelery.snapshot.Camera` 16 | 7. Start `celeryd` with celery beat (`-B`): `./manage.py celeryd -B -l INFO` 17 | 8. Run a task: 18 | 9. `./manage.py shell` 19 | 10. `from demoapp.tasks import add` 20 | 11. `add.delay(2,2)` 21 | 12. and you should then see things happening in the Celery Beat process and in the [Django Admin](https://docs.djangoproject.com/en/1.8/ref/contrib/admin/) 22 | 23 | Lots of steps involved and that's why I put together this project to provide an isolated example of using django-celery that worked for me in 2015 on Django 1.7 24 | The less steps it takes, the more likely you are to get it running sooner. Cheers! 25 | 26 | -------------------------------------------------------------------------------- /proj/settings.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | # ^^^ The above is required if you want to import from the celery 3 | # library. If you don't have this then `from celery.schedules import` 4 | # becomes `proj.celery.schedules` in Python 2.x since it allows 5 | # for relative imports by default. 6 | 7 | import os 8 | 9 | # Celery settings 10 | import djcelery 11 | djcelery.setup_loader() 12 | 13 | # http://fearofcode.github.io/blog/2013/01/15/how-to-scrub-sensitive-information-from-django-settings-dot-py-files/ 14 | # rom proj.settings_secret import * 15 | # SECURITY WARNING: keep the secret key used in production secret! 16 | SECRET_KEY = 'x2$s&0z2xehpnt_99i8q3)4)t*5q@+n(+6jrqz4@rt%a8fdf+!' 17 | 18 | # c9IP = os.environ.get('IP') 19 | # BROKER_URL = 'amqp://guest:guest@{}//'.format(c9IP) 20 | # BROKER_URL = 'amqp://guest:guest@localhost:5672//' 21 | # BROKER_URL = 'django://' # warning: slow, experiemental option 22 | # BROKER_URL = 'redis://localhost:6379/0' # http://docs.celeryproject.org/en/latest/getting-started/brokers/redis.html#results 23 | 24 | BROKER_URL = "localhost" 25 | BROKER_BACKEND = "redis" 26 | BROKER_USER = "" 27 | BROKER_PASSWORD = "" 28 | # BROKER_VHOST = "0" 29 | 30 | REDIS_HOST = "localhost" 31 | REDIS_PORT = 6379 32 | REDIS_DB = 0 33 | REDIS_CONNECT_RETRY = True 34 | 35 | 36 | # # http://docs.celeryproject.org/en/latest/getting-started/brokers/redis.html#caveats 37 | BROKER_TRANSPORT_OPTIONS = { 38 | 'fanout_prefix': True, 39 | 'visibility_timeout': 3600 # 1 hour for redis: http://docs.celeryproject.org/en/latest/getting-started/brokers/redis.html#visibility-timeout 40 | } 41 | 42 | #: Only add pickle to this list if your broker is secured 43 | #: from unwanted access (see userguide/security.html) 44 | CELERY_ACCEPT_CONTENT = ['json'] 45 | CELERY_TASK_SERIALIZER = 'json' 46 | CELERY_RESULT_SERIALIZER = 'json' 47 | # CELERY_RESULT_BACKEND = 'redis' 48 | CELERY_RESULT_BACKEND = "djcelery.backends.database:DatabaseBackend" #django-celery database result backend 49 | # CELERY_RESULT_BACKEND='djcelery.backends.cache:CacheBackend' #django-celery cached database result backend 50 | CELERY_SEND_EVENTS = True 51 | CELERY_TASK_RESULT_EXPIRES = 10 52 | CELERYBEAT_SCHEDULER = "djcelery.schedulers.DatabaseScheduler" 53 | #CELERY_RESULT_BACKEND='djcelery.backends.database:DatabaseBackend' # http://docs.celeryproject.org/en/master/django/first-steps-with-django.html#using-the-django-orm-cache-as-a-result-backend 54 | #CELERY_SEND_EVENTS = True # http://docs.celeryproject.org/en/latest/configuration.html?highlight=events#celery-send-events 55 | 56 | # Django settings for proj project. 57 | 58 | DEBUG = True 59 | TEMPLATE_DEBUG = DEBUG 60 | 61 | ADMINS = ( 62 | # ('Your Name', 'your_email@example.com'), 63 | ) 64 | 65 | MANAGERS = ADMINS 66 | 67 | DATABASES = { 68 | 'default': { 69 | # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 70 | 'ENGINE': 'django.db.backends.sqlite3', 71 | 'NAME': 'test.db', # path to database file if using sqlite3. 72 | 'USER': '', # Not used with sqlite3. 73 | 'PASSWORD': '', # Not used with sqlite3. 74 | 'HOST': '', # Set to empty string for localhost. 75 | # Not used with sqlite3. 76 | 'PORT': '', # Set to empty string for default. 77 | # Not used with sqlite3. 78 | } 79 | } 80 | 81 | # Local time zone for this installation. Choices can be found here: 82 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 83 | # although not all choices may be available on all operating systems. 84 | # In a Windows environment this must be set to your system time zone. 85 | TIME_ZONE = 'US/Eastern' 86 | 87 | # Language code for this installation. All choices can be found here: 88 | # http://www.i18nguy.com/unicode/language-identifiers.html 89 | LANGUAGE_CODE = 'en-us' 90 | 91 | SITE_ID = 1 92 | 93 | # If you set this to False, Django will make some optimizations so as not 94 | # to load the internationalization machinery. 95 | USE_I18N = True 96 | 97 | # If you set this to False, Django will not format dates, numbers and 98 | # calendars according to the current locale. 99 | USE_L10N = True 100 | 101 | # If you set this to False, Django will not use timezone-aware datetimes. 102 | USE_TZ = True 103 | 104 | # Absolute filesystem path to the directory that will hold user-uploaded files. 105 | # Example: "/home/media/media.lawrence.com/media/" 106 | MEDIA_ROOT = '' 107 | 108 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a 109 | # trailing slash. 110 | # Examples: "http://media.lawrence.com/media/", "http://example.com/media/" 111 | MEDIA_URL = '' 112 | 113 | # Absolute path to the directory static files should be collected to. 114 | # Don't put anything in this directory yourself; store your static files 115 | # in apps' "static/" subdirectories and in STATICFILES_DIRS. 116 | # Example: "/home/media/media.lawrence.com/static/" 117 | STATIC_ROOT = '' 118 | 119 | # URL prefix for static files. 120 | # Example: "http://media.lawrence.com/static/" 121 | STATIC_URL = '/static/' 122 | 123 | # Additional locations of static files 124 | STATICFILES_DIRS = ( 125 | # Put strings here, like "/home/html/static" or "C:/www/django/static". 126 | # Always use forward slashes, even on Windows. 127 | # Don't forget to use absolute paths, not relative paths. 128 | ) 129 | 130 | # List of finder classes that know how to find static files in 131 | # various locations. 132 | STATICFILES_FINDERS = ( 133 | 'django.contrib.staticfiles.finders.FileSystemFinder', 134 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 135 | ) 136 | 137 | # List of callables that know how to import templates from various sources. 138 | TEMPLATE_LOADERS = ( 139 | 'django.template.loaders.filesystem.Loader', 140 | 'django.template.loaders.app_directories.Loader', 141 | ) 142 | 143 | MIDDLEWARE_CLASSES = ( 144 | 'django.middleware.common.CommonMiddleware', 145 | 'django.contrib.sessions.middleware.SessionMiddleware', 146 | 'django.middleware.csrf.CsrfViewMiddleware', 147 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 148 | 'django.contrib.messages.middleware.MessageMiddleware', 149 | # simple clickjacking protection: 150 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 151 | ) 152 | 153 | ROOT_URLCONF = 'proj.urls' 154 | 155 | # Python dotted path to the WSGI application used by Django's runserver. 156 | WSGI_APPLICATION = 'proj.wsgi.application' 157 | 158 | TEMPLATE_DIRS = ( 159 | # Put strings here, like "/home/html/django_templates" 160 | # or "C:/www/django/templates". 161 | # Always use forward slashes, even on Windows. 162 | # Don't forget to use absolute paths, not relative paths. 163 | ) 164 | 165 | INSTALLED_APPS = ( 166 | 'django.contrib.auth', 167 | 'django.contrib.contenttypes', 168 | 'django.contrib.sessions', 169 | 'django.contrib.sites', 170 | 'django.contrib.messages', 171 | 'django.contrib.staticfiles', 172 | #'kombu.transport.django', 173 | 'kombu.transport.django.KombuAppConfig', 174 | 'djcelery', 175 | 'demoapp', 176 | 'django.contrib.admin', # https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ 177 | # 'django.contrib.admindocs', # https://docs.djangoproject.com/en/1.8/ref/contrib/admin/admindocs/ 178 | ) 179 | 180 | # A sample logging configuration. The only tangible logging 181 | # performed by this configuration is to send an email to 182 | # the site admins on every HTTP 500 error when DEBUG=False. 183 | # See http://docs.djangoproject.com/en/dev/topics/logging for 184 | # more details on how to customize your logging configuration. 185 | LOGGING = { 186 | 'version': 1, 187 | 'disable_existing_loggers': False, 188 | 'filters': { 189 | 'require_debug_false': { 190 | '()': 'django.utils.log.RequireDebugFalse' 191 | } 192 | }, 193 | 'handlers': { 194 | 'mail_admins': { 195 | 'level': 'ERROR', 196 | 'filters': ['require_debug_false'], 197 | 'class': 'django.utils.log.AdminEmailHandler' 198 | } 199 | }, 200 | 'loggers': { 201 | 'django.request': { 202 | 'handlers': ['mail_admins'], 203 | 'level': 'ERROR', 204 | 'propagate': True, 205 | }, 206 | } 207 | } --------------------------------------------------------------------------------