Django autodiscovery no longer requires an argument to work.

If `app.autodiscover_tasks()` is called without a packages argument, the
Django fixup will now take the list of modules from the app config registry.

Closes #2596
This commit is contained in:
Ask Solem 2015-09-04 12:01:21 -07:00
Родитель 320ae3c971
Коммит e436454d02
4 изменённых файлов: 36 добавлений и 10 удалений

Просмотреть файл

@ -348,17 +348,31 @@ class Celery(object):
return setup_security(allowed_serializers, key, cert,
store, digest, serializer, app=self)
def autodiscover_tasks(self, packages, related_name='tasks', force=False):
def autodiscover_tasks(self, packages=None,
related_name='tasks', force=False):
if force:
return self._autodiscover_tasks(packages, related_name)
signals.import_modules.connect(promise(
self._autodiscover_tasks, (packages, related_name),
), weak=False, sender=self)
def _autodiscover_tasks(self, packages, related_name='tasks', **kwargs):
# argument may be lazy
packages = packages() if callable(packages) else packages
self.loader.autodiscover_tasks(packages, related_name)
def _autodiscover_tasks(self, packages, related_name, **kwargs):
if packages:
return self._autodiscover_tasks_from_names(packages, related_name)
return self._autodiscover_tasks_from_fixups(related_name)
def _autodiscover_tasks_from_names(self, packages, related_name):
# packages argument can be lazy
return self.loader.autodiscover_tasks(
packages() if callable(packages) else packages, related_name,
)
def _autodiscover_tasks_from_fixups(self, related_name):
return self._autodiscover_tasks_from_names([
pkg for fixup in self._fixups
for pkg in fixup.autodiscover_tasks()
if hasattr(fixup, 'autodiscover_tasks')
], related_name=related_name)
def send_task(self, name, args=None, kwargs=None, countdown=None,
eta=None, task_id=None, producer=None, connection=None,

Просмотреть файл

@ -57,6 +57,7 @@ class DjangoFixup(object):
# Need to add project directory to path
sys.path.append(os.getcwd())
self._settings = symbol_by_name('django.conf:settings')
self.app.loader.now = self.now
self.app.loader.mail_admins = self.mail_admins
@ -83,6 +84,14 @@ class DjangoFixup(object):
def mail_admins(self, subject, body, fail_silently=False, **kwargs):
return self._mail_admins(subject, body, fail_silently=fail_silently)
def autodiscover_tasks(self):
try:
from django.apps import apps
except ImportError:
return self._settings.INSTALLED_APPS
else:
return [config.name for config in apps.get_app_configs()]
@cached_property
def _mail_admins(self):
return symbol_by_name('django.core.mail:mail_admins')

Просмотреть файл

@ -92,10 +92,10 @@ autodiscover these modules:
.. code-block:: python
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
app.autodiscover_tasks()
With the line above Celery will automatically discover tasks in reusable
apps if you follow the ``tasks.py`` convention::
With the line above Celery will automatically discover tasks from all
of your installed apps, following the ``tasks.py`` convention::
- app1/
- tasks.py
@ -104,6 +104,7 @@ apps if you follow the ``tasks.py`` convention::
- tasks.py
- models.py
This way you do not have to manually add the individual modules
to the :setting:`CELERY_IMPORTS` setting. The ``lambda`` so that the
autodiscovery can happen only when needed, and so that importing your

Просмотреть файл

@ -4,7 +4,7 @@ import os
from celery import Celery
from django.conf import settings
from django.apps import apps as django_apps
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings')
@ -14,7 +14,9 @@ app = Celery('proj')
# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
# load task modules from all registered Django app configs.
app.autodiscover_tasks()
@app.task(bind=True)