问题使用Django项目的调度程序

时间:2016-11-17 18:05:53

标签: python django heroku cron apscheduler

您好stackoverflow社区,我在安排一个cron作业时遇到问题,该作业需要抓取一个网站并将其作为模型(MOVIE)的一部分存储在数据库中。问题是模型似乎在Procfile执行之前加载。我应该如何创建一个在后台内部运行并将抓取的信息存储到数据库中的cron作业?这是我的代码:

Procfile:

    web: python manage.py runserver 0.0.0.0:$PORT
    scheduler: python cinemas/scheduler.py

scheduler.py:

# More code above
from cinemas.models import Movie
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()

@sched.scheduled_job('cron', day_of_week='mon-fri', hour=0, minutes=26)    
def get_movies_playing_now():
  global url_movies_playing_now
  Movie.objects.all().delete()
  while(url_movies_playing_now):
    title = []
    description = []
    #Create BeatifulSoup Object with url link
    s = requests.get(url_movies_playing_now, headers=headers)
    soup = bs4.BeautifulSoup(s.text, "html.parser")
    movies = soup.find_all('ul', class_='w462')[0]

    #Find Movie's title
    for movie_title in movies.find_all('h3'):
        title.append(movie_title.text)
    #Find Movie's description
    for movie_description in soup.find_all('ul',
                                           class_='w462')[0].find_all('p'):
        description.append(movie_description.text.replace(" [More]","."))

    for t, d in zip(title, description):
        m = Movie(movie_title=t, movie_description=d)
        m.save()

    #Go to the next page to find more movies
    paging = soup.find( class_='pagenating').find_all('a', class_=lambda x:
                                                      x != "inactive")
    href = ""
    for p in paging:
        if "next" in p.text.lower():
            href = p['href']
    url_movies_playing_now = href

sched.start()
# More code below

from django.db import models

电影院/ models.py:

#Create your models here.

class Movie(models.Model):
    movie_title = models.CharField(max_length=200)
    movie_description = models.CharField(max_length=20200)

这是我在运行Job时遇到的错误。

2016-11-17T17:57:06.074914 + 00:00 app [scheduler.1]:Traceback(最近一次调用最后一次): 2016-11-17T17:57:06.074931 + 00:00 app [scheduler.1]:文件“cinemas / scheduler.py”,第2行,in 2016-11-17T17:57:06.075058 + 00:00 app [scheduler.1]:import cineplex 2016-11-17T17:57:06.075060 + 00:00 app [scheduler.1]:文件“/app/cinemas/cineplex.py”,第1行,in 2016-11-17T17:57:06.075173 + 00:00 app [scheduler.1]:来自cinemas.models导入电影 2016-11-17T17:57:06.075196 + 00:00 app [scheduler.1]:文件“/app/cinemas/models.py”,第5行,in 2016-11-17T17:57:06.075295 + 00:00 app [scheduler.1]:class Movie(models.Model): 2016-11-17T17:57:06.075297 + 00:00 app [scheduler.1]:文件“/app/.heroku/python/lib/python3.5/site-packages/django/db/models/base.py” ,第105行, new 2016-11-17T17:57:06.075414 + 00:00 app [scheduler.1]:app_config = apps.get_containing_app_config(module) 2016-11-17T17:57:06.075440 + 00:00 app [scheduler.1]:文件“/app/.heroku/python/lib/python3.5/site-packages/django/apps/registry.py”,行237,在get_containing_app_config中 2016-11-17T17:57:06.075585 + 00:00 app [scheduler.1]:self.check_apps_ready() 2016-11-17T17:57:06.075586 + 00:00 app [scheduler.1]:文件“/app/.heroku/python/lib/python3.5/site-packages/django/apps/registry.py”,行124,在check_apps_ready中 2016-11-17T17:57:06.075703 + 00:00 app [scheduler.1]:提升AppRegistryNotReady(“应用尚未加载。”) 2016-11-17T17:57:06.075726 + 00:00 app [scheduler.1]:django.core.exceptions.AppRegistryNotReady:尚未加载应用。

如果我不包含Model对象,Cron作业可以正常工作。我应该如何使用Model对象每天运行这项工作而不失败?

由于

2 个答案:

答案 0 :(得分:2)

那是因为你不能只导入Django包,模型等;为了正常工作,Django内部需要从manage.py触发的初始化。我总是将长时间运行的非Web命令作为自定义管理命令编写,而不是尝试重新创建所有这些命令(请参阅https://docs.djangoproject.com/en/1.10/howto/custom-management-commands/)。例如,如果您的应用是cinemas,您会:

  • 创建./cinemas/management/commands/scheduler.py
  • 在该文件中,子类django.core.management.base.BaseCommand(该子类必须被称为Command
  • 在该课程中,覆盖handle()。在您的情况下,您可以拨打sched.start()
  • 您的Procfile将有scheduler: python manage.py scheduler

希望有所帮助。

答案 1 :(得分:0)

您可以通过在sceduler.py

的顶部添加以下行来解决问题
import django
django.setup()

在django文档中it says

  

如果您正在使用Django的“独立”组件 - 例如,编写加载一些Django模板并呈现它们的Python脚本,或者使用ORM来获取某些数据 - 此外还需要一个步骤配置设置。

     

在设置DJANGO_SETTINGS_MODULE或调用configure()之后,您需要调用django.setup()来加载设置并填充Django的应用程序注册表。例如:

import django
from django.conf import settings
from myapp import myapp_defaults

settings.configure(default_settings=myapp_defaults, DEBUG=True)
django.setup()

# Now this script or any imported module can use any part of Django it needs.
from myapp import models

我将DJANGO_SETTINGS_MODULE设置为配置变量,因此没有将其添加到我的调度程序中。