2016-11-17 2 views
2

Hi communauté stackoverflow, J'ai un problème pour programmer un travail cron qui nécessite de gratter un site web et de le stocker comme partie du modèle (MOVIE) dans la base de données. Le problème est que le modèle semble être chargé avant l'exécution de Procfile. Comment créer un travail cron qui s'exécute en interne en arrière-plan et qui stocke les informations récupérées dans la base de données? Voici mes codes:QUESTIONS Définir des tâches Cron dans Procfile (Heroku) en utilisant apscheduler pour le projet Django

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 

cinémas/models.py:

#Create your models here. 

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

Ceci est l'erreur que je reçois quand le travail est exécuté.

2016-11-17T17: 57: 06.074914 + 00: 00 app [planificateur.1]: Traceback (appel le plus récent en dernier): 2016-11-17T17: 57: 06.074931 + 00: 00 app [planificateur. 1]: Fichier "cinemas/scheduler.py", ligne 2, en 2016-11-17T17: 57: 06.075058 + 00: 00 app [planificateur.1]: import cineplex 2016-11-17T17: 57: 06.075060+ 00:00 app [scheduler.1]: Fichier "/app/cinemas/cineplex.py", ligne 1, dans 2016-11-17T17: 57: 06.075173 + 00: 00 app [scheduler.1]: dans les cinémas. modèles importer Film 2016-11-17T17: 57: 06.075196 + 00: 00 app [scheduler.1]: Fichier "/app/cinemas/models.py", ligne 5, en 2016-11-17T17: 57: 06.075295 +00: 00 application [scheduler.1]: classe Movie (models.Model): 2016-11-17T17: 57: 06.075297 + 00: 00 application [scheduler.1]: Fichier " /app/.heroku/python/lib/python3.5/site-packages/django/db/models/base.py ", ligne 105, en nouveau 2016-11-17T17: 57: 06.075414 + 00: 00 app [planificateur.1]: app_config = apps.get_containing_app_config (module) 2016-11-17T17: 57: 06.075440 + 00: 00 app [planificateur.1]: fichier "/app/.heroku/python/lib/python3. 5/packages-site/django/apps/registry.py ", ligne 237, dans get_containing_app_config 2016-11-17T17: 57: 06.075585 + 00: 00 app [planificateur.1]: self.check_apps_ready() 2016-11 -17T17: 57: 06.075586 + 00: 00 app [scheduler.1]: fichier "/app/.heroku/python/lib/python3.5/site-packages/django/apps/registry.py", ligne 124, dans check_apps_ready 2016-11-17T17: 57: 06.075703 + 00: 00 app [scheduler.1]: augmente AppRegistryNotReady ("Les applications ne sont pas encore chargées.") 2016-11-17T17: 57: 06.075726 + 00: 00 app [sch eduler.1]: django.core.exceptions.AppRegistryNotReady: Les applications ne sont pas encore chargées.

Le travail Cron fonctionne correctement si je n'inclue pas les objets Modèle. Comment dois-je exécuter ce travail tous les jours en utilisant des objets Modèle sans échec?

Merci

Répondre

2

C'est parce que vous ne pouvez pas importer les packages Django, modèles, etc .; Pour fonctionner correctement, les composants internes de Django nécessitent une initialisation déclenchée par manage.py. Plutôt que d'essayer de recréer tout cela moi-même, j'écris toujours des commandes non Web de longue durée en tant que commande de gestion personnalisée (voir https://docs.djangoproject.com/en/1.10/howto/custom-management-commands/). Par exemple, si votre application est cinemas, vous devez:

  • Créer ./cinemas/management/commands/scheduler.py.
  • Dans ce fichier, sous-classe django.core.management.base.BaseCommand (cette sous-classe doit être appelée Command)
  • Dans cette classe, passer outre handle().Dans votre cas, c'est là que vous appelleriez sched.start()
  • Votre Procfile aurait alors scheduler: python manage.py scheduler

espoir qui aide.

+0

Merci! Cela fonctionne pour moi :) –

0

Vous pouvez résoudre le problème en ajoutant les lignes suivantes en haut de votre sceduler.py

import django 
django.setup() 

Dans la documentation de django it says

Si vous utilisez des composants de Django « autonome "- par exemple, en écrivant un script Python qui charge certains modèles Django et les restitue, ou utilise l'ORM pour récupérer des données - il y a encore une étape dont vous aurez besoin en plus de la configuration des paramètres. Après avoir défini DJANGO_SETTINGS_MODULE ou appelé configure(), vous devrez appeler django.setup() pour charger vos paramètres et remplir le registre des applications de Django. Par exemple:

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 

Je mis DJANGO_SETTINGS_MODULE comme une variable de configuration n'a donc pas l'ajouter à mon planificateur.