Skip to main content

Developer Guide: Adding City Forecasts to ClimWeb

This guide explains three ways to add city forecast data to ClimWeb, and how to retrieve forecasts via the read API (see Retrieving Forecast Data). For a more hands-on guide visit the Forecast Manager Guide:


1. Using the API

Endpoint

  • POST /api/forecasts/post

Authentication

  • Requires Token.
  • Obtain a token via POST to /api/token/ (TokenAuthentication) with payload
{
    "username":"your_username",
    "password":"your_password"
}
  • Add header: Authorization: Token <token>

Payload Example

{
  "forecast_date": "2026-03-11",
  "effective_time": "06:00:00",
  "source": "local",
  "replace_existing": true,
  "city_forecasts": [
    {
      "city": "nairobi",
      "condition": "Partly Cloudy",
      "data_values": {
        "max_temp": 28.5,
        "min_temp": 18.2,
        "humidity": 64
      }
    }
  ]
}

Example Python Script

import requests
API_URL = "http://<domain_name>/api/forecasts/post"
TOKEN = "your_token_here"
payload = { ... }
headers = {"Authorization": f"Token {TOKEN}", "Content-Type": "application/json"}
response = requests.post(API_URL, json=payload, headers=headers)
print(response.status_code)
print(response.json())

2. Automated City Forecast from Meteorological Providers

  • This is simply implemented by enabling the automated forecasts checkbox under Forecast Settings > Forecast Source, then choosing a forecast provider. Forecasts are refreshed automatically on a schedule. For each city they are stored hourly for the current day and at 3-hourly periods (00, 03, 06, 09, 12, 15, 18, 21) for the following days.
  • Two providers are supported:
    • yr.no (Meteorological Norway)source value yr.
    • Open-Meteosource value open_meteo.
  • Each provider exposes its own set of source fields (e.g. air temperature, humidity, wind speed, precipitation) which an admin maps onto local forecast parameters under the parameter-mapping settings.

Manual pull: automated forecasts refresh on a schedule, but you can trigger an extra pull on demand. When automation is enabled, a Pull forecasts now button appears on the Forecasts listing. The pull runs as a Celery task (it does not block the web request), so the button returns immediately and the forecasts appear on the listing once the worker finishes. If a pull is already queued or running, clicking again won't start a second one. (If auto-publish is off, the pulled forecasts are saved as drafts for review.) The same run is available from the command line via python manage.py generate_auto_forecast.

Celery worker required. The manual pull runs as a Celery task, so the host project needs a worker consuming the queue:

celery -A <your_project> worker -l INFO

Without a worker the button reports that it could not start the pull, rather than silently queueing work nobody will run. Concurrent pulls are prevented by a cache key with a 30-minute TTL, so a worker that dies mid-pull releases the guard by itself.

Changed in 0.6.7: this previously used django-background-tasks and its separate manage.py process_tasks worker. Projects that never ran that worker queued rows which were never consumed — the pull never happened, and the button disabled itself permanently because it treated the leftover row as "still running".

To read more about the providers visit:


3. Manual CSV Upload

  • Use the admin interface or dedicated upload page to upload city forecast data via CSV. Visit guide here.
  • Download the CSV template .
  • Fill in city forecast data in the template.
  • Upload the CSV file using the web interface (typically via a form).
  • The system will parse, validate, and import the data.
  • Optionally, set 'overwrite existing' if you want to replace previous forecasts.

Adding Cities

Cities (the locations forecasts are attached to) can be added in three ways:

  1. Manually via the Cities snippet in the Wagtail admin.
  2. CSV upload — Cities listing > Import Cities, then upload a CSV with city name, latitude, and longitude columns.
  3. Import from GeoNames — Cities listing > Import from GeoNames (see below).

Importing from GeoNames

This pulls cities from the free GeoNames web service for a given country, so you don't have to assemble a CSV by hand. It is available both from the Wagtail admin and as a management command.

One-time setup

  1. Create a free account at geonames.org.
  2. Enable web services on the account. This is the step that is easy to miss: after registering, log in, open your account page, and click "Click here to enable" under Free Web Services. Until this is done, every request is rejected (see Troubleshooting). Activation can take up to an hour.
  3. In the Wagtail admin, go to Forecast Settings > Other Settings > GeoNames username and save your account username (not the email address).

How the list is kept small

A single country can have tens of thousands of GeoNames entries, but most are not cities — they are rivers, mountains, roads, parks, and farms. The import reduces this in two layers:

  1. Filter by feature class. Only GeoNames feature class P (populated places) is considered, which removes the non-settlement records.
  2. Select with an admin seats + fill by population strategy, capped at a maximum:
    • Always include administrative seats — PPLC (national capital), PPLA (regional/first-order capitals), and PPLA2 (district/second-order seats) — ordered by rank, so every administrative centre is covered even if it has a small population.
    • Fill the remaining slots with the highest-population populated places not already chosen, up to the configured maximum.

This guarantees both administrative coverage and a manageable list. The default cap is 200 and is adjustable per import.

Relevant GeoNames feature codes (full list at geonames.org/export/codes.html):

Code Meaning
PPLC National capital
PPLA Seat of a first-order admin division (regional/provincial capital)
PPLA2PPLA5 Seats of second- to fifth-order admin divisions (district/ward seats)
PPL Generic populated place (towns, villages — selected by population)

From the admin

  1. Go to the Cities listing and click Import from GeoNames.
  2. Enter the ISO 3166 alpha-2 country code (e.g. MW for Malawi, KE for Kenya).
  3. Set the maximum cities (default 200).
  4. Optionally tick Update existing cities to refresh the coordinates of cities that already exist (otherwise duplicates are skipped).
  5. Click Preview to see exactly which cities will be imported (name, type, region, population, coordinates), then Import to save them.

From the command line

# Import (uses the username saved in Forecast Settings; default max 200)
python manage.py import_geonames_cities --country MW

# Preview only — list what would be imported, write nothing
python manage.py import_geonames_cities --country KE --max 150 --dry-run

# Update the locations of cities that already exist instead of skipping them
python manage.py import_geonames_cities --country MW --overwrite

# Override the configured username for a single run
python manage.py import_geonames_cities --country MW --username my_geonames_user
Option Description
--country ISO 3166 alpha-2 country code (required).
--max Maximum number of cities to import (default 200).
--username GeoNames username; defaults to the one saved in Forecast Settings.
--overwrite Update existing cities' locations instead of skipping them.
--dry-run List the selected cities without writing to the database.

Notes & troubleshooting

  • City names are unique. An existing city is skipped unless you pass --overwrite (CLI) or tick Update existing cities (admin), in which case its location is updated.
  • GeoNames error: user account not enabled to use the free webservice or a 401 response means web services have not been enabled on the account — complete step 2 of the setup above and wait for activation.
  • GeoNames error: the daily limit ... has been exceeded means the account's free request quota is used up; it resets the next day.
  • A GeoNames username must be set (in settings or via --username) or the import will refuse to run.

Retrieving Forecast Data (Read API)

All read endpoints serve published forecasts only (drafts are withheld until reviewed) and are publicly accessible — no token required.

Method & Endpoint Description
GET /api/cities List cities. Optional ?name= filter (case-insensitive contains).
GET /api/forecasts All published forecasts as GeoJSON. Optional ?forecast_date= and ?effective_period= filters.
GET /api/forecast_mobile Single nearest-city forecast in Met Norway timeseries format (see below).
GET /api/forecast-settings Configured data parameters and effective periods.
GET /api/weather-icons Available weather condition icons with full URLs.
GET /api/forecast_template.csv Download the CSV upload template.

Mobile Forecast Endpoint

  • GET /api/forecast_mobile?lat=<lat>&lon=<lon>

Returns the forecast for the city nearest to the supplied coordinates, structured like the Met Norway location forecast model. The lat/lon query parameters are required and are matched to the closest stored city. Each timeseries step carries only:

  • time — the forecast's effective datetime (UTC).
  • data.instant.details — the city's forecast data values.
  • data.next_1_hours.summary.symbol_code — the weather condition symbol.

The meta block reports whether the match was the exact city or the nearest one, plus the unit for each parameter.

Example Response

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [35.05, -15.04]
  },
  "properties": {
    "meta": {
      "updated_at": "2026-06-25T09:00:00Z",
      "city": "Lilongwe",
      "location_source": "nearest",
      "location_description": "Forecast for the nearest city (Lilongwe).",
      "units": {
        "air_temperature": "°C",
        "cloud_area_fraction": "%",
        "precipitation_amount": "mm",
        "wind_from_direction": "degrees",
        "wind_speed": "m/s"
      }
    },
    "timeseries": [
      {
        "time": "2026-06-25T06:00:00Z",
        "data": {
          "instant": {
            "details": {
              "air_temperature": 20.5,
              "wind_speed": 2.3
            }
          },
          "next_1_hours": {
            "summary": { "symbol_code": "clearsky_day" }
          }
        }
      }
    ]
  }
}

Note: lat is treated as latitude and lon as longitude. The units and symbol_code values reflect how each parameter and weather condition is configured in the admin.


Notes

  • All methods require valid city and parameter references.
  • For API and automated methods, ensure authentication is set up.
  • For manual upload, follow the template format and check for errors after upload.
  • All weather symbols used are from yr.no

For further details, see the API documentation .

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

forecastmanager-0.6.8.tar.gz (1.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

forecastmanager-0.6.8-py3-none-any.whl (1.9 MB view details)

Uploaded Python 3

File details

Details for the file forecastmanager-0.6.8.tar.gz.

File metadata

  • Download URL: forecastmanager-0.6.8.tar.gz
  • Upload date:
  • Size: 1.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for forecastmanager-0.6.8.tar.gz
Algorithm Hash digest
SHA256 7fb2784daa44b201412d87148d333d5d2083c09be6cc9a3deec5d2043cf79756
MD5 1383e8b946ef37498b74bc49e2846e94
BLAKE2b-256 387629115f828caa212c1bee299239b767db1dac20f6529c5a0bced1af7dddce

See more details on using hashes here.

Provenance

The following attestation bundles were made for forecastmanager-0.6.8.tar.gz:

Publisher: publish.yml on wmo-raf/forecastmanager

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file forecastmanager-0.6.8-py3-none-any.whl.

File metadata

File hashes

Hashes for forecastmanager-0.6.8-py3-none-any.whl
Algorithm Hash digest
SHA256 e8391ac7342ab7fabd47cba53793b87a6fef842f30880fefa378bb7ce3f300b4
MD5 3acf29e774df5033277eec183279917d
BLAKE2b-256 aa2da6049e6106cde32a1fa91d649c7ea2950f71aba414a9e66539df85600c9f

See more details on using hashes here.

Provenance

The following attestation bundles were made for forecastmanager-0.6.8-py3-none-any.whl:

Publisher: publish.yml on wmo-raf/forecastmanager

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.6.8 This release

2 files

0.6.7

2 files

0.6.6

2 files

0.6.5

2 files

0.6.4

2 files

0.6.3

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.9

2 files

0.5.8

2 files

0.5.7

2 files

0.5.6

2 files

0.5.5

2 files

0.5.4

2 files

0.5.3

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.4.9

2 files

0.4.8

2 files

0.4.7

2 files

0.4.6

2 files

0.4.5

2 files

0.4.4

2 files

0.4.3

2 files

0.4.2

2 files

0.4.1

2 files

0.3.0

2 files

0.2.0

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

0.0.9

2 files

0.0.8

2 files

0.0.7

2 files

0.0.6

2 files

0.0.5

2 files

0.0.4

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page