Example apps

Warehouse Pick Lists

Warehouse pick-list REST API: units, pick zones, waves and tote labels as incremental computed columns over Json order lines

One app.py with 1 table, 5 computed columns, 6 HTTP routes. Needs pixeltable[serve]>=0.7.15. Updated 2026-10-08.

app.py
"""Warehouse Pick-List API built with Pixeltable.
Orders arrive with a Json list of lines. Total units, pick zones, estimated pick time, pick wave and the
tote label are computed columns (Python UDFs in udfs.py) that Pixeltable keeps up to date on every insert
and update. A FastAPIRouter serves insert / update / delete routes plus index-backed queries for the
pick floor (open orders in a wave, one order's tote label).
Layout: UDFs live in udfs.py (imported below); this file holds the tables, the @pxt.query functions and the routes.
Run locally:
pxt schema update app.py picking
pxt service run app.py picking
See README.md for the walkthrough and Pixeltable Cloud deployment.
"""
import pixeltable as pxt
from pixeltable.serving import FastAPIRouter
from udfs import label_text, pick_minutes, total_units, wave, zones
# ---- tables ----
TableModel = pxt.model_base()
class Orders(TableModel, name='orders', has_default_idxs=False):
order_id = pxt.Column(type=pxt.String, primary_key=True)
customer: pxt.String
lines: pxt.Json
rush: pxt.Bool | None
status: pxt.String # open -> picking -> packed -> shipped
notes: pxt.Json | None
# computed columns: chained UDFs, recomputed when an input column changes
units = total_units(lines)
zone_list = zones(lines)
est_minutes = pick_minutes(units, zone_list, rush)
wave_name = wave(zone_list, rush)
tote_label = label_text(order_id, wave_name, zone_list)
__indexes__ = [pxt.BtreeIndex(status), pxt.BtreeIndex(wave_name), pxt.BtreeIndex(customer)]
# ---- queries ----
@pxt.query
def wave_queue(wave_name: str, status: str):
"""Orders in a pick wave with a given status, longest pick first (index-backed)."""
return (
Orders.where((Orders.wave_name == wave_name) & (Orders.status == status))
.select(Orders.order_id, Orders.customer, Orders.units, Orders.est_minutes, Orders.tote_label)
.order_by(Orders.est_minutes, asc=False)
)
@pxt.query
def order_label(order_id: str):
"""One order's tote label and pick estimate (0 rows -> 404)."""
return Orders.where(Orders.order_id == order_id).select(
Orders.order_id, Orders.tote_label, Orders.est_minutes, Orders.status
)
@pxt.query
def customer_orders(customer: str):
"""A customer's orders, newest id first."""
return (
Orders.where(Orders.customer == customer)
.select(Orders.order_id, Orders.status, Orders.units, Orders.wave_name)
.order_by(Orders.order_id, asc=False)
)
# ---- routes ----
picking_api = FastAPIRouter(name='picking_api')
picking_api.add_insert_route(
Orders,
path='/orders',
inputs=[Orders.order_id, Orders.customer, Orders.lines, Orders.rush, Orders.status, Orders.notes],
outputs=[Orders.order_id, Orders.units, Orders.zone_list, Orders.est_minutes, Orders.wave_name, Orders.tote_label],
)
picking_api.add_update_route(
Orders,
path='/orders/update',
inputs=[Orders.status, Orders.lines, Orders.rush],
outputs=[Orders.order_id, Orders.status, Orders.units, Orders.wave_name, Orders.est_minutes],
)
picking_api.add_delete_route(Orders, path='/orders/cancel')
picking_api.add_query_route(path='/waves/queue', query=wave_queue, method='get')
picking_api.add_query_route(path='/orders/label', query=order_label, one_row=True, method='get')
picking_api.add_query_route(path='/customers/orders', query=customer_orders, method='get')

Run it

Needs uv. The routes then answer on port 8000.

terminal
git clone https://github.com/pierrebrunelle/pixeltable-warehouse-picklists
cd pixeltable-warehouse-picklists
uv sync
uv run pxt schema update app.py picking
uv run python seed.py picking
uv run pxt service run app.py picking --port 8000