"""Celery tasks for fetching weather data from OpenWeatherMap API for django_owm."""importloggingfromdecimalimportDecimalfromceleryimportshared_taskfromdjango.appsimportappsfrom.app_settingsimportOWM_API_RATE_LIMITSfrom.app_settingsimportOWM_MODEL_MAPPINGSfrom.utils.apiimportcheck_api_limitsfrom.utils.apiimportget_api_call_countsfrom.utils.apiimportlog_api_callfrom.utils.apiimportmake_api_callfrom.utils.savingimportsave_error_logfrom.utils.savingimportsave_weather_datalogger=logging.getLogger(__name__)
[docs]@shared_task@check_api_limitsdeffetch_weather(location_ids:Decimal|int|None=None)->None:"""Fetch current weather data for all locations."""WeatherLocationModel=apps.get_model(OWM_MODEL_MAPPINGS.get("WeatherLocation"))iflocation_idsisnotNone:locations=WeatherLocationModel.objects.filter(id__in=location_ids)else:locations=WeatherLocationModel.objects.all()ifnotWeatherLocationModel:logger.error("WeatherLocation model is not configured.")locations=[]else:locations=WeatherLocationModel.objects.all()api_name="one_call"forlocationinlocations:calls_last_minute,_=get_api_call_counts(api_name)ifcalls_last_minute>=OWM_API_RATE_LIMITS.get(api_name,{}).get("calls_per_minute",60):logger.warning("API call limit per minute exceeded. Stopping task.")breakdata=make_api_call(location.latitude,location.longitude)ifdata:save_weather_data(location,data)log_api_call(api_name)else:error_message="Failed to fetch weather data"save_error_log(location,api_name,error_message)