在django中使用apscheduler 執行計劃任務的實現方法
對於任何軟體開發人員而言,為將來計劃任務都是必不可少的工具。 儘管我們建立的許多程式設計旨在響應明確的觸發或使用者事件,但定期執行的後臺程序也同樣重要。
“每個星期一早晨更新結果。”
“每天晚上分批下單。”
甚至具有每日請求限制的第三方API也隱式要求這種行為。
“我們只能每五分鐘請求一次更新。”
幸運的是,許多聰明的人已經解決了這個問題,並且不難找到python本地解決方案。 Advanced Python Scheduler(APS)是一個很好的選擇,它具有簡單,直觀的API以及同類產品中的一些最佳文件。
對於此專案,我們將專注於將APS提供的排程技術與您的常規Django應用程式整合:洛杉磯天氣應用程式,該應用程式定期輪詢第三方天氣api以進行模型更新。
目標是比Django教程進行更深入的探索,同時不要在任何方向上陷入困境。
I.安裝APS和其他依賴項
在您的專案目錄中,建立一個虛擬環境並激活它
virtualenv env . env/bin/activate
根據本指南安裝和配置PostgreSQL。 在此階段,我們只需要在您的計算機上啟動並執行SQL管理器即可。
另外,我發現使用PgAdmin PostgreSQL GUI有幫助。 在您的計算機上進行設定的詳細資訊可以在這裡找到(使用Python3)。
使用pip安裝所有必需的軟體包(注意,psycopg2適用於PostgreSQL):
pip install apscheduler django psycopg2 requests II. Build your app Create a new Django project: django-admin.py startproject advancedScheduler cd advancedScheduler python manage.py startapp weather
在這個新目錄(根目錄)中,您將看到另一個名為advancedScheduler的資料夾。 這是Django專案目錄。
為避免兩地同名的混淆,我們僅將“根目錄”稱為“根目錄”。 讓下面的圖作為我們跳資料夾冒險的路線圖。
[ super_project_directory/ ] | +----[ env/ ] <-- Virtualenv stuff | +----[ advancedScheduler/ ] <-- the Root Directory | +----[ advancedScheduler/ ] <-- the Django Project Directory | +----[ weather/ ] <-- the Django App Directory
儘管主要專注於演示排程程式的功能,但讓我們花點時間連線Django應用。
我們首先要將天氣應用新增到專案的INSTALLED_APPS中。 該檔案位於advancedScheduler / settings.py檔案中。
INSTALLED_APPS = [ 'django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','weather' ]
接下來,將新的網址格式新增到advancedScheduler / urls.py檔案中:
path('',include('weather.urls'))
毫不奇怪,我們的下一步將是將該urls.py檔案新增到weather app目錄中。 將以下程式碼包含在weather / urls.py中:
from django.conf.urls import url from weather import views urlpatterns = [ url(r'^$',views.MainPage.as_view()) ]
在天氣應用程式目錄中建立一個模板資料夾。 將index.html檔案新增到此新資料夾。
以下是我們的MTV。
模型
from django.db import models from datetime import datetime class Forecast(models.Model): timestamp = models.DateTimeField() temperatue = models.DecimalField(max_digits=12,decimal_places=2) description = models.CharField(max_length=150) city = models.CharField(max_length=150) def save(self,*args,**kwargs): if not self.id: self.timestamp = datetime.utcnow() return super(Forecast,self).save(*args,**kwargs) Template <div style="text-align: center"> <h5>Currently in</h5> <h3>{{city}}</h3> <h4>{{temperature_in_f}} F | {{temperature_in_c}} C</h4> <h4>{{desctiprion}}</h4> <p><em>Last updated {{utc_update_time}} GMT</em></p> </div> View import decimal from datetime import datetime from django.shortcuts import render from django.views.generic import TemplateView from weather.models import Forecast class MainPage(TemplateView): def get(self,request,**kwargs): latest_forecast = Forecast.objects.latest('timestamp') city = latest_forecast.city temperature_in_c = latest_forecast.temperatue temperature_in_f = (latest_forecast.temperatue * decimal.Decimal(1.8)) + 32 description = latest_forecast.description.capitalize timestamp = "{t.year}/{t.month:02d}/{t.day:02d} - {t.hour:02d}:{t.minute:02d}:{t.second:02d}".format( t=latest_forecast.timestamp) return render( request,'index.html',{ 'city':city,'temperature_in_c': temperature_in_c,'temperature_in_f': round(temperature_in_f,2),'desctiprion': description,'utc_update_time': timestamp})
三, 建立資料庫連線並遷移模型
在advancedScheduler / settings.py中,將DATABASES值更改為:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2','NAME': 'advancedScheduler','USER': 'some_user_name','PASSWORD': 'some_password','HOST': 'localhost','PORT': '',} }
您應該從上述PostgreSQL配置指南(此處和此處)瞭解USER,PASSWORD和PORT的值。
與PostgreSQL建立連線後,就該遷移我們的模型了。 導航到“根目錄”並鍵入:
python manage.py makemigrations python manage.py migrate
這樣,我們的模型應該已經對映到資料庫了。 繼續並檢查所有內容。 不用擔心,我會在這裡等你回來。
IV。 預測API
時間到了有趣的部分。 我正在從OpenWeatherMap(一個免費的天氣API)中提取我的預報資料,該API將為您授予帶有有效電子郵件地址的訪問令牌。
現在,由於它在概念上不同於我們的表示層,因此讓我們在根目錄中建立一個新的ForecastUpdater資料夾。 在其中,我們將新增兩個檔案:一個空白的__init__.py檔案和一個ForecastApi.py檔案。 請參閱路線圖以供參考。
[ super_project_directory/ ] | +----[ env/ ] | +----[ advancedScheduler/ ] <-- the Root Directory | +----[ advancedScheduler/ ] | +----[ weather/ ] | +----[ forecastUpdater/ ] <-- the new Updater Module | +----< __init__.py > <--+ | |-- two new Python files +----< forecastApi.py > <--+ import requests from weather.models import Forecast def _get_forecast_json(): url = 'http://api.openweathermap.org/data/2.5/weather' encoded_city_name = 'Los%20Angeles' country_code = 'us' access_token = 'your_access_token' r = requests.get('{0}?q={1},{2}&APPID={3}'.format( url,encoded_city_name,country_code,access_token)) try: r.raise_for_status() return r.json() except: return None def update_forecast(): json = _get_forecast_json() if json is not None: try: new_forecast = Forecast() # open weather map gives temps in Kelvin. We want celsius. temp_in_celsius = json['main']['temp'] - 273.15 new_forecast.temperatue = temp_in_celsius new_forecast.description = json['weather'][0]['description'] new_forecast.city = json['name'] new_forecast.save() print("saving...\n" + new_forecast) except: pass
在這裡,有一些事情要注意。 異常處理遠非健壯。 錯誤只是被丟棄了—過度的沉默是唯一出問題的跡象。
其次,我們在程式碼中指定洛杉磯。 將您的伺服器配置到所需的任何位置。
同樣重要的是要注意,update_forecast()不帶任何引數。 我們很快就會看到,我們的高階python計劃程式具有嚴格的無引數規則。 甚至帶有孤獨的self引數的方法也不會飛。
五,高階Python計劃程式
我們已經建立了模型。 我們可以通過呼叫API來更新資料。 現在我們需要做的就是指定訪問該API的頻率,這樣我們就可以在不超出資料訪問限制的情況下提供合理的最新資訊。
在ForecastUpdater模組中,新增一個updater.py檔案。 在這裡,我們將使用Advanced Python Scheduler設定我們的預測更新的節奏。
OpenWeatherMaps使用條款允許在一個小時內保持60個通話,以保持免費等級; 每五分鐘更新一次就足夠了。
from datetime import datetime from apscheduler.schedulers.background import BackgroundScheduler from forecastUpdater import forecastApi def start(): scheduler = BackgroundScheduler() scheduler.add_job(forecastApi.update_forecast,'interval',minutes=5) scheduler.start()
這可能是您可以找到的最簡單的APS實現。 如果您檢視他們的網站或GitHub上的幾個工作示例,則將發現一個完整的功能和設定工具箱,您可以使用這些工具來進行計時,以使其儘可能的細緻。
按照我們想要的方式配置了排程程式後,就可以將其連線到Django應用了。
理想情況下,我們希望在排程程式上按一次播放,然後讓它執行其任務。 我們需要一種一致且可靠的方式來初始化時間表一次且僅一次。 對於我們而言,Django正是這種型別的執行時初始化邏輯的地方。
在weather / apps.py檔案中,您會找到一個名為WeatherConfig的類的存根,該類繼承自Django的AppConfig類。
class WeatherConfig(AppConfig): name = 'weather'
為了讓Django知道它需要在啟動時啟動更新程式,我們覆蓋了AppConfig.ready()方法。
from django.apps import AppConfig class WeatherConfig(AppConfig): name = 'weather' def ready(self): from forecastUpdater import updater updater.start()
重要的是要記住,由於繼承的複雜性,此覆蓋的任何匯入都必須位於ready()方法的主體內。 Django還警告不要在我們的覆蓋中直接與資料庫進行互動; 生產,除錯,風雨無阻,每次啟動天氣應用程式時,都會執行此程式碼。
最後,我們現在需要在advancedScheduler / settings.py中再次更新INSTALLED_APPS變數。 Django需要知道我們要使用自定義配置來執行天氣應用。
INSTALLED_APPS = [ 'django.contrib.admin','weather.apps.WeatherConfig' ]
VI。 全部放在一起
而已。 在這一點上,我們可以啟動我們的應用程式,然後讓更新程式執行其操作。
python manage.py runserver --noreload
-noreload標誌可防止Django啟動天氣應用的第二個例項-這是除錯模式下的預設行為。 第二個例項意味著我們所有計劃的任務將觸發兩次。
最初,我們的結果看起來不完整。 由於我們將更新程式邏輯安排為每五分鐘執行一次,因此我們不停地抽動一下……為了使事情變得有趣,縮短審慎重新整理之間的間隔可能是明智的選擇,或者在初始化時呼叫一次update_forecast()。
七。 最後的想法
我們做到了! 我們的天氣應用已準備好與世界分享(請在此處檢視我的資訊)。
Advanced Python Scheduler是任何Python開發人員都知道的好工具。 它在直觀的API後面隱藏了非常常見的業務需求的複雜性。 考慮一下,安裝程式只用了三行程式碼。
該專案的真正技巧是與Django框架進行互動-配置,遷移,初始化。 然後,任務自動化成為事後的想法。 五分鐘內您就完成了。
https://github.com/kmhoran/la-weather-app
以上所述是小編給大家介紹的在django中使用apscheduler 執行計劃任務的實現方法,希望對大家有所幫助!