Skip to main content

Django zone-based courier shipping cost calculator — by Nitesh Kumar Singh (nkscoder)

Project description

Courier — Generic Django Zone-Based Shipping Cost Calculator

PyPI version Python Python 3.12 Django License: MIT

Author: Nitesh Kumar Singh · GitHub: @nkscoder

A generic, reusable Django courier app for calculating zone-based shipping costs by weight, quantity, and destination. Works out of the box with built-in country/region models, or plugs into your existing location tables. Built by Nitesh Kumar Singh (nkscoder).

Keywords: django courier · generic shipping calculator · zone-based shipping · weight pricing · reusable django app · nkscoder · nitesh kumar singh · python shipping


Features

  • Generic by design — built-in CourierCountry / CourierRegion models, no core app required
  • Configurable pricing — domestic multiplier, international surcharge %, weight units, thresholds
  • Zone-based pricing — map countries and regions to shipping zones
  • Weight slab lookup — automatic cost lookup by weight brackets
  • Multi-unit support — grams, kilograms, and pounds (gram, kgs, lbs)
  • JSON API endpoint — real-time shipping quotes via HTTP GET
  • Python API — call calculate_courier_cost() from checkout, cart, or background jobs
  • Custom zone resolver — plug in your own location models with one settings hook
  • Django Admin — manage countries, regions, zones, and weight costs

Requirements

  • Python 3.8–3.12 (including 3.12)
  • Django 3.2+

Installation

pip install nkscoder-courier

With Django Admin CSV import/export:

pip install "nkscoder-courier[admin]"

From GitHub:

pip install git+https://github.com/nkscoder/courier.git

Quick start

# settings.py
INSTALLED_APPS = [
    ...
    "courier",
]

COURIER_DOMESTIC_COUNTRY_NAME = "India"
COURIER_INTERNATIONAL_SURCHARGE_PERCENT = 22
python manage.py migrate courier
# urls.py
urlpatterns = [
    path("courier/", include("courier.urls")),
]

Usage

Python API (recommended)

from courier.calculator import calculate_courier_cost

total = calculate_courier_cost(
    weight=1.5,
    quantity=2,
    weight_unit="kgs",
    country_id=country.pk,
    region_id=region.pk,  # optional for domestic regions
)

Backward-compatible alias:

from courier import courier_cost

total = courier_cost(weight=500, quantity=1, weight_unit="gram", country=1, state=3)

HTTP API

GET /courier/?weight=500&quantity=2&weight_unit=gram&country=1&region=3

Response:

{"total": 150}
Parameter Description
weight Package weight
quantity Number of packages
weight_unit gram, kgs, or lbs
country Country PK
region or state Region PK (for domestic destinations)

Configuration

All settings use the COURIER_ prefix:

Setting Default Description
COURIER_COUNTRY_MODEL courier.CourierCountry Country model label
COURIER_REGION_MODEL courier.CourierRegion Region/state model label
COURIER_DOMESTIC_COUNTRY_NAME India Fallback domestic country name
COURIER_INTERNATIONAL_SURCHARGE_PERCENT 22 Surcharge for non-domestic destinations
COURIER_HEAVY_WEIGHT_THRESHOLD_KG 20 Heavy shipment threshold
COURIER_WEIGHT_PADDING_KG 0.500 Padding added to billable weight
COURIER_WEIGHT_INCREMENT_KG 0.500 Domestic weight multiplier increment
COURIER_DEFAULT_WEIGHT_UNIT gram Default unit for API requests
COURIER_DOMESTIC_USE_WEIGHT_MULTIPLIER True Per-increment pricing for domestic
COURIER_ZONE_RESOLVER None Custom (country_id, region_id) -> (connection, surcharge)

Plug into your own location models

# settings.py
COURIER_COUNTRY_MODEL = "myapp.Country"
COURIER_REGION_MODEL = "myapp.State"

def resolve_courier_zone(country_id, region_id):
    from courier.models import ZoneConnection
    # your lookup logic
    return connection, apply_surcharge

COURIER_ZONE_RESOLVER = resolve_courier_zone

Mark domestic countries with is_domestic=True on your model, or rely on COURIER_DOMESTIC_COUNTRY_NAME.


Admin setup

  1. Courier Country — add destinations; mark domestic with is_domestic
  2. Courier Region — add states/provinces under domestic countries
  3. Zone — create shipping zones (Zone A, Zone B, …)
  4. Zone Connection — link zones to countries and/or regions
  5. Weight Cost — set price per weight slab for each zone

How pricing works

  1. Resolve the destination zone from country/region via ZoneConnection
  2. Normalize weight to grams and compute total billable weight
  3. Look up the matching WeightCost slab for that zone
  4. Domestic: multiply slab rate by weight increments (configurable)
  5. International: apply configurable surcharge % on the base rate

Development

git clone git@github.com:nkscoder/courier.git
cd courier
pip install -e ".[admin]"
python manage.py migrate
python manage.py test courier

Changelog

1.1.1

  • Renamed PyPI package to nkscoder-courier (name courier was taken on PyPI)
  • Fixed GitHub Actions publish workflow with PYPI_API_TOKEN

1.1.0

  • Generic built-in CourierCountry / CourierRegion models (no core dependency)
  • New calculate_courier_cost() service API
  • Configurable settings via COURIER_* prefix
  • Optional custom COURIER_ZONE_RESOLVER hook
  • Improved admin with search and filters

1.0.0

  • Initial PyPI release by Nitesh Kumar Singh (nkscoder)

Author & Links

Author Nitesh Kumar Singh
GitHub github.com/nkscoder
Repository github.com/nkscoder/courier
PyPI pypi.org/project/nkscoder-courier

License

MIT License — Copyright (c) 2020-2026 Nitesh Kumar Singh (nkscoder)

Project details


Download files

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

Source Distribution

nkscoder_courier-1.1.1.tar.gz (13.1 kB view details)

Uploaded Source

Built Distribution

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

nkscoder_courier-1.1.1-py3-none-any.whl (13.0 kB view details)

Uploaded Python 3

File details

Details for the file nkscoder_courier-1.1.1.tar.gz.

File metadata

  • Download URL: nkscoder_courier-1.1.1.tar.gz
  • Upload date:
  • Size: 13.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for nkscoder_courier-1.1.1.tar.gz
Algorithm Hash digest
SHA256 355877bf732269d0d268c584b71261b8a82ce558f43eba5be0e9cfb96ca6c9a4
MD5 101e822be9c88ebf784b6efbd952bf46
BLAKE2b-256 37680da334a337297d1879d671a918ca2623d09bda52b367d17d24b4cdba3d81

See more details on using hashes here.

File details

Details for the file nkscoder_courier-1.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for nkscoder_courier-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 58da4833888ab2248cbd0fd254b835f70d868825c3854f6ffe99649bafcce431
MD5 46936e8d657471fc114e28af9c58b123
BLAKE2b-256 0f2efedb2867bec498d5b11ee8fc4f3f746d73b0131bc25d2fe25ac341ccad90

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page