title: Connect new celery periodic task in django
body: <p>It's not a question but help to those who will find that the declaration of periodic tasks described in celery 4.0.1 documentation is hard to integrate in django:
  <a href="http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html#entries" rel="noreferrer">http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html#entries</a></p>
  
  <p>copy paste celery config file <code>main_app/celery.py</code>:</p>
  
  <pre><code>from celery import Celery
  from celery.schedules import crontab
  
  app = Celery()
  
  @app.on_after_configure.connect
  def setup_periodic_tasks(sender, **kwargs):
      # Calls test('hello') every 10 seconds.
      sender.add_periodic_task(10.0, test.s('hello'), name='add every 10')
  
      # Calls test('world') every 30 seconds
      sender.add_periodic_task(30.0, test.s('world'), expires=10)
  
      # Executes every Monday morning at 7:30 a.m.
      sender.add_periodic_task(
          crontab(hour=7, minute=30, day_of_week=1),
          test.s('Happy Mondays!'),
      )
  
  @app.task
  def test(arg):
      print(arg)
  </code></pre>
  
  <h3>Question</h3>
  
  <p>But what if we use django and our tasks are placed in another app? With celery <code>4.0.1</code> we no longer have <code>@periodic_task</code> decorator. So let's see what we can do. </p>
  
  <h3>First case</h3>
  
  <p>If you prefer to keep tasks and their schedule close to each other:</p>
  
  <p><code>main_app/some_app/tasks.py</code></p>
  
  <pre><code>from main_app.celery import app as celery_app
  
  @celery_app.on_after_configure.connect
      def setup_periodic_tasks(sender, **kwargs):
          # Calls test('hello') every 10 seconds.
          sender.add_periodic_task(10.0, test.s('hello'))
  
  @celery_app.task
  def test(arg):
      print(arg)
  </code></pre>
  
  <p>We can run <code>beat</code> in debug mode:</p>
  
  <pre><code>celery -A main_app beat -l debug
  </code></pre>
  
  <p>and we will see that there's no such periodic task.</p>
  
  <h3>Second case</h3>
  
  <p>We can try to describe all periodic tasks in config file like this:</p>
  
  <p><code>main_app/celery.py</code></p>
  
  <pre><code>...
  app = Celery()
  
  @app.on_after_configure.connect
  def setup_periodic_tasks(sender, **kwargs):
      # Calls test('hello') every 10 seconds.
      from main_app.some_app.tasks import test
      sender.add_periodic_task(10.0, test.s('hello'))
  ...
  </code></pre>
  
  <p>The result is the same. But it will behave differently that you can see with manual debugging via pdb. In first example <code>setup_periodic_tasks</code> callback will not be fired at all. But in second example we'll get <code>django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.</code> (this exception will not be print out)</p>