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.2.tar.gz (13.3 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.2-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: nkscoder_courier-1.1.2.tar.gz
  • Upload date:
  • Size: 13.3 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.2.tar.gz
Algorithm Hash digest
SHA256 085b1e31d63df34f1f9afeda99e6285cb8e717b789b53bfd390f2dea262e00fa
MD5 4ff1133c1a7fe725fcefdb4bc0831732
BLAKE2b-256 59db1f61f1809a5a6f01e08517d7eff01e2a7a65249bf7a1141e243e94f5e922

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for nkscoder_courier-1.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d4faca257dc2ac7d3c38abc300dd2591b7a024b444bd0f2773e51eaac806c044
MD5 6c6b8eb1d5ade36206397d2d31074891
BLAKE2b-256 6043416a04bd25081d9d81d061e17580086feb9fbef56400f8fb28a332ae0b79

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