Ich habe an einer Web-App mit Django gearbeitet und bin neugierig, ob es eine Möglichkeit gibt, einen Job periodisch zu planen.
Im Grunde möchte ich nur die Datenbank durchgehen und regelmäßig und regelmäßig Berechnungen/Aktualisierungen vornehmen, aber ich kann anscheinend keine Dokumentation dazu finden.
Weiß jemand, wie man das einrichtet?
Zur Klarstellung: Ich weiß, dass ich einen cron
-Job einrichten kann, aber ich bin neugierig, ob es in Django eine Funktion gibt, die diese Funktionalität bietet. Ich möchte, dass die Leute diese App selbst bereitstellen können, ohne viele Konfigurationsschritte durchführen zu müssen (vorzugsweise Null).
Ich habe in Erwägung gezogen, diese Aktionen "rückwirkend" auszulösen, indem ich einfach prüfe, ob ein Job ausgeführt werden sollte, seit eine Anfrage zuletzt an die Site gesendet wurde. Ich hoffe jedoch auf etwas saubereres.
Eine Lösung, die ich verwendet habe, ist dies zu tun:
1) Erstellen Sie einen benutzerdefinierten Verwaltungsbefehl , z.
python manage.py my_cool_command
2) Verwenden Sie cron
(unter Linux) oder at
(unter Windows), um meinen Befehl zu den erforderlichen Zeiten auszuführen.
Dies ist eine einfache Lösung, für die kein starker AMQP-Stack installiert werden muss. Es gibt jedoch gute Vorteile, wenn man etwas wie Sellerie verwendet, wie in den anderen Antworten erwähnt. Bei Celery ist es besonders schön, dass Sie Ihre Anwendungslogik nicht in Crontab-Dateien verteilen müssen. Die cron-Lösung funktioniert jedoch sehr gut für kleine bis mittelgroße Anwendungen, bei denen Sie keine großen externen Abhängigkeiten wünschen.
BEARBEITEN:
In späteren Versionen von Windows ist der Befehl at
für Windows 8, Server 2012 und höher veraltet. Sie können schtasks.exe
für dieselbe Verwendung verwenden.
Celery ist eine verteilte Task-Warteschlange, die auf AMQP (RabbitMQ) basiert. Es behandelt auch periodische Aufgaben cronartig (siehe periodische Aufgaben ). Abhängig von Ihrer App ist es vielleicht einen Blick wert.
Sellerie ist mit Django ( docs ) ziemlich einfach einzurichten, und bei periodischen Aufgaben werden übersprungene Aufgaben bei Ausfallzeiten übersprungen. Celery verfügt auch über integrierte Wiederholungsmechanismen für den Fall, dass eine Aufgabe fehlschlägt.
Wir haben aus meiner Sicht eine strukturierte App gefunden. dass die Lösung von Brian über alle Anspielungen hinausgeht. Würde mich über Feedback freuen!
https://github.com/tivix/Django-cron
Es gibt einen Verwaltungsbefehl:
./manage.py runcrons
Das macht den Job. Jeder Cron wird als Klasse modelliert (also alle als OO) und jeder Cron läuft mit einer anderen Frequenz. Wir stellen sicher, dass derselbe Cronentyp nicht parallel läuft (falls Cron selbst länger als ihre Frequenz laufen müssen!)
Vielen Dank!
Wenn Sie ein Standard-POSIX-Betriebssystem verwenden, verwenden Sie cron .
Wenn Sie Windows verwenden, verwenden Sie at .
Schreiben Sie einen Django-Verwaltungsbefehl an
Finde heraus, auf welcher Plattform sie sich befinden.
Führen Sie entweder den entsprechenden "AT" -Befehl für Ihre Benutzer aus, oder aktualisieren Sie die Crontab für Ihre Benutzer.
Interessante neue steckbare Django-App: Django-Chronograph
Sie müssen nur einen cron-Eintrag hinzufügen, der als Timer fungiert, und Sie haben eine sehr schöne Django-Administrationsoberfläche für die Ausführung der Skripts.
Schauen Sie sich Django Poor Man's Cron an, eine Django-App, die Spambots, Suchmaschinen-Indizierungsroboter und dergleichen verwendet, um geplante Aufgaben in ungefähr regelmäßigen Abständen auszuführen
RabbitMQ und Celery bieten mehr Funktionen und Aufgaben als Cron. Wenn das Fehlschlagen von Aufgaben kein Problem ist und Sie der Meinung sind, dass Sie beim nächsten Anruf mit fehlerhaften Aufgaben fertig werden, ist Cron ausreichend.
Mit Sellerie & AMQP können Sie die fehlerhafte Aufgabe erledigen und diese wird erneut von einem anderen Arbeiter ausgeführt (Celery-Mitarbeiter überwachen die nächste Aufgabe), bis das max_retries
-Attribut der Aufgabe erreicht ist. Sie können sogar Aufgaben ausführen, wenn ein Fehler auftritt, z. B. das Protokollieren des Fehlers oder das Senden einer E-Mail an den Administrator, sobald der max_retries
erreicht wurde.
Sie können Celery- und AMQP-Server verteilen, wenn Sie Ihre Anwendung skalieren müssen.
Brian Neals Vorschlag, Verwaltungsbefehle über cron auszuführen, funktioniert gut, aber wenn Sie nach etwas robusterem suchen (aber nicht so kompliziert wie Celery), würde ich mir eine Bibliothek wie Kronos anschauen:
# app/cron.py
import kronos
@kronos.register('0 * * * *')
def task():
pass
Ich persönlich benutze cron, aber die Jobs Scheduling Teile von Django-Erweiterungen sehen interessant aus.
Fügen Sie Folgendes in Ihre Datei cron.py ein:
#!/usr/bin/python
import os, sys
sys.path.append('/path/to/') # the parent directory of the project
sys.path.append('/path/to/project') # these lines only needed if not on path
os.environ['Django_SETTINGS_MODULE'] = 'myproj.settings'
# imports and code below
Ich hatte vor einer Weile genau die gleiche Anforderung und endete letztendlich mit APScheduler ( User Guide ).
Es macht das Planen von Jobs extrem einfach und macht es unabhängig von der anforderungsbasierten Ausführung von Code. Das folgende ist ein einfaches Beispiel, das ich in meinem Code verwendet habe.
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
job = None
def tick():
print('One tick!')\
def start_job():
global job
job = scheduler.add_job(tick, 'interval', seconds=3600)
try:
scheduler.start()
except:
pass
Hoffe das hilft jemandem!
Ich habe gerade über diese ziemlich einfache Lösung nachgedacht:
Sie können Parameter hinzufügen, aber nur Parameter zur URL hinzufügen.
Sag mir, was ihr denkt.
[Update] Ich benutze jetzt den runjob-Befehl von Django-extensions anstelle von curl.
Mein Cron sieht ungefähr so aus:
@hourly python /path/to/project/manage.py runjobs hourly
... und so weiter für täglich, monatlich usw. '. Sie können es auch so einrichten, dass ein bestimmter Job ausgeführt wird.
Ich finde es überschaubarer und sauberer. Erfordert keine Zuordnung einer URL zu einer Ansicht. Definieren Sie einfach Ihre Jobklasse und Crontab und Sie sind fertig.
Obwohl es kein Teil von Django ist, ist Airflow ein jüngeres Projekt (Stand 2016), das für die Aufgabenverwaltung nützlich ist.
Airflow ist ein Workflow-Automatisierungs- und Zeitplanungssystem, mit dem Daten-Pipelines erstellt und verwaltet werden können. Eine webbasierte Benutzeroberfläche bietet dem Entwickler eine Reihe von Optionen zum Verwalten und Anzeigen dieser Pipelines.
Airflow ist in Python geschrieben und wird mit Flask erstellt.
Airflow wurde von Maxime Beauchemin bei Airbnb entwickelt und im Frühjahr 2015 als Open-Source-Produkt angeboten. Im Winter 2016 trat er dem Inkubationsprogramm der Apache Software Foundation bei. Hier ist die Git-Projektseite und einige Zusatzinformationen Hintergrundinformationen .
nach dem Teil des Codes kann ich alles wie meine Ansichten schreiben.py :)
#######################################
import os,sys
sys.path.append('/home/administrator/development/store')
os.environ['Django_SETTINGS_MODULE']='store.settings'
from Django.core.management impor setup_environ
from store import settings
setup_environ(settings)
#######################################
from http://www.cotellese.net/2007/09/27/running-external-scripts-against-Django-models/
Sie sollten sich unbedingt Django-q! .__ ansehen. Es erfordert keine zusätzliche Konfiguration und hat möglicherweise alles, um Produktionsprobleme bei kommerziellen Projekten zu lösen.
Es ist aktiv entwickelt und integriert sich sehr gut mit Django, Django ORM, Mongo, Redis. Hier ist meine Konfiguration:
# Django-q
# -------------------------------------------------------------------------
# See: http://Django-q.readthedocs.io/en/latest/configure.html
Q_CLUSTER = {
# Match recommended settings from docs.
'name': 'DjangoORM',
'workers': 4,
'queue_limit': 50,
'bulk': 10,
'orm': 'default',
# Custom Settings
# ---------------
# Limit the amount of successful tasks saved to Django.
'save_limit': 10000,
# See https://github.com/Koed00/Django-q/issues/110.
'catch_up': False,
# Number of seconds a worker can spend on a task before it's terminated.
'timeout': 60 * 5,
# Number of seconds a broker will wait for a cluster to finish a task before presenting it again. This needs to be
# longer than `timeout`, otherwise the same task will be processed multiple times.
'retry': 60 * 6,
# Whether to force all async() calls to be run with sync=True (making them synchronous).
'sync': False,
# Redirect worker exceptions directly to Sentry error reporter.
'error_reporter': {
'sentry': RAVEN_CONFIG,
},
}
Ich hatte heute etwas Ähnliches mit Ihrem Problem.
Ich wollte nicht, dass es vom Server durch cron (und die meisten libs waren am Ende nur cron-Helfer) gehandhabt wurden.
Also habe ich ein Scheduling-Modul erstellt und an das init angehängt.
Dies ist nicht der beste Ansatz, aber es hilft mir, den gesamten Code an einem einzigen Ort zu haben und dessen Ausführung mit der Haupt-App in Verbindung zu stehen.
Ja, die obige Methode ist so toll. Und ich habe einige von ihnen ausprobiert. Endlich fand ich eine Methode wie diese:
from threading import Timer
def sync():
do something...
sync_timer = Timer(self.interval, sync, ())
sync_timer.start()
Genau wie rekursiv .
Ok, ich hoffe, diese Methode kann Ihre Anforderungen erfüllen. :)
Ich verwende Sellerie, um meine periodischen Aufgaben zu erstellen. Zuerst müssen Sie es wie folgt installieren:
pip install Django-celery
Vergessen Sie nicht, Django-celery
in Ihren Einstellungen zu registrieren und dann könnten Sie so etwas tun:
from celery import task
from celery.decorators import periodic_task
from celery.task.schedules import crontab
from celery.utils.log import get_task_logger
@periodic_task(run_every=crontab(minute="0", hour="23"))
def do_every_midnight():
#your code
Ich bin mir nicht sicher, ob dies für alle nützlich sein wird, da ich andere Benutzer des Systems zur Planung der Jobs bereitstellen musste, ohne ihnen Zugriff auf den eigentlichen Taskplaner des Servers (Windows) zu geben.
Beachten Sie, dass Benutzer Zugriff auf einen freigegebenen Ordner auf dem Server haben, in dem sie die erforderliche Befehls-/Task-/BAT-Datei erstellen können. Diese Aufgabe kann dann mit dieser App geplant werden.
App-Name ist Django_Windows_Scheduler
Eine modernere Lösung (im Vergleich zu Sellerie) ist Django Q: https://Django-q.readthedocs.io/de/latest/index.html
Es hat eine großartige Dokumentation und ist leicht zu grokieren. Die Windows-Unterstützung fehlt, da Windows Prozess-Forking nicht unterstützt. Es funktioniert jedoch gut, wenn Sie Ihre Entwicklungsumgebung mit dem Windows für Linux-Subsystem erstellen.
Wenn Sie etwas zuverlässiger als Sellerie möchten, versuchen Sie TaskHawk, das auf AWS SQS/SNS basiert.
Eine einfache Möglichkeit ist, einen benutzerdefinierten Shell-Befehl zu schreiben, siehe Django Documentation und ihn mit einem Cronjob unter Linux auszuführen. Ich würde jedoch empfehlen, einen Nachrichtenbroker wie RabbitMQ und Sellerie zu verwenden. Vielleicht können Sie Dieses Tutorial anschauen.
Bei einfachen angedockten Projekten konnte ich keine passende Antwort finden.
Also habe ich eine Barebones-Lösung geschrieben, ohne dass externe Bibliotheken oder Trigger erforderlich sind, die von alleine laufen. Kein externer OS-Cron erforderlich, sollte in jeder Umgebung funktionieren.
Es funktioniert, indem Sie eine Middleware hinzufügen: middleware.py
import threading
def should_run(name, seconds_interval):
from application.models import CronJob
from Django.utils.timezone import now
try:
c = CronJob.objects.get(name=name)
except CronJob.DoesNotExist:
CronJob(name=name, last_ran=now()).save()
return True
if (now() - c.last_ran).total_seconds() >= seconds_interval:
c.last_ran = now()
c.save()
return True
return False
class CronTask:
def __init__(self, name, seconds_interval, function):
self.name = name
self.seconds_interval = seconds_interval
self.function = function
def cron_worker(*_):
if not should_run("main", 60):
return
# customize this part:
from application.models import Event
tasks = [
CronTask("events", 60 * 30, Event.clean_stale_objects),
# ...
]
for task in tasks:
if should_run(task.name, task.seconds_interval):
task.function()
def cron_middleware(get_response):
def middleware(request):
response = get_response(request)
threading.Thread(target=cron_worker).start()
return response
return middleware
models/cron.py
:
from Django.db import models
class CronJob(models.Model):
name = models.CharField(max_length=10, primary_key=True)
last_ran = models.DateTimeField()
settings.py
:
MIDDLEWARE = [
...
'application.middleware.cron_middleware',
...
]