Marina Berth Booking
Marina berth booking API: string primary keys, binary columns, berth fees and stay bands as computed columns
One app.py with 3 tables, 4 computed columns, 9 HTTP routes. Needs pixeltable[serve]>=0.7.14. Updated 2026-10-01.
app.py
"""Marina Berth Booking API built with Pixeltable.pxt schema update app.py marinapxt service run app.py marina"""import pixeltable as pxtimport pixeltable.functions as pxtffrom pixeltable.serving import FastAPIRouterfrom udfs import berth_fee, size_class, slip_label, stay_band# ---- tables ----TableModel = pxt.model_base()class Slips(TableModel, name='slips'):slip_id = pxt.Column(type=pxt.String, primary_key=True)dock: pxt.Stringlength_m: pxt.Floatpower_amps: pxt.Intlabel = slip_label(dock, slip_id, length_m)class Vessels(TableModel, name='vessels'):id = pxt.Column(value=pxtf.uuid.uuid7(), primary_key=True)name: pxt.Stringloa_m: pxt.Floatowner: pxt.Stringnote_bin: pxt.Binary | Nonesize = size_class(loa_m)class Bookings(TableModel, name='bookings'):id = pxt.Column(value=pxtf.uuid.uuid7(), primary_key=True)slip_id: pxt.Stringvessel_name: pxt.Stringloa_m: pxt.Floatnights: pxt.Intfee = berth_fee(loa_m, nights)band = stay_band(nights)# ---- queries ----@pxt.querydef slips_that_fit(loa_m: float):"""Slips long enough for a vessel, tightest fit first."""return Slips.where(Slips.length_m >= loa_m).select(Slips.slip_id, Slips.label, Slips.power_amps).order_by(Slips.length_m)@pxt.querydef slip_bookings(slip_id: str):return Bookings.where(Bookings.slip_id == slip_id).select(Bookings.id, Bookings.vessel_name, Bookings.nights, Bookings.fee, Bookings.band).order_by(Bookings.vessel_name)# ---- routes ----marina_api = FastAPIRouter(name='marina_api')marina_api.add_insert_route(Slips, path='/slips', inputs=[Slips.slip_id, Slips.dock, Slips.length_m, Slips.power_amps],outputs=[Slips.slip_id, Slips.label])marina_api.add_insert_route(Vessels, path='/vessels', inputs=[Vessels.name, Vessels.loa_m, Vessels.owner],outputs=[Vessels.id, Vessels.size])marina_api.add_insert_route(Bookings, path='/bookings',inputs=[Bookings.slip_id, Bookings.vessel_name, Bookings.loa_m, Bookings.nights],outputs=[Bookings.id, Bookings.fee, Bookings.band])marina_api.add_update_route(Bookings, path='/bookings/extend', inputs=[Bookings.nights],outputs=[Bookings.id, Bookings.nights, Bookings.fee, Bookings.band])marina_api.add_delete_route(Bookings, path='/bookings/cancel')marina_api.add_compute_route(Bookings, path='/band', inputs=[Bookings.nights], outputs=[Bookings.band])marina_api.add_compute_route(Bookings, path='/quote', inputs=[Bookings.loa_m, Bookings.nights],outputs=[Bookings.fee, Bookings.band])marina_api.add_query_route(path='/slips/fit', query=slips_that_fit, method='get')marina_api.add_query_route(path='/slips/bookings', query=slip_bookings, method='get')
What app.py declares
Each row links to its line.
- runs on insert
- stored
- index
- route
serves marina_api
- POST/slipsinsert, slipstakes slip_id, dock, length_m, power_amps; returns slip_id, labelL62
- POST/vesselsinsert, vesselstakes name, loa_m, owner; returns id, sizeL64
- POST/bookingsinsert, bookingstakes slip_id, vessel_name, loa_m, nights; returns id, fee, bandL66
- POST/bookings/extendupdate, bookingstakes nights; returns id, nights, fee, bandL69
- POST/bookings/canceldelete, bookingsL71
- POST/bandcompute, bookingstakes nights; returns bandL72
- POST/quotecompute, bookingstakes loa_m, nights; returns fee, bandL73
- GET/slips/fitquery, slips_that_fittakes loa_mL75
- GET/slips/bookingsquery, slip_bookingstakes slip_idL76
Run it
Needs uv. The routes then answer on port 8000.
terminal
git clone https://github.com/pierrebrunelle/pixeltable-marina-berthscd pixeltable-marina-berthsuv syncuv run pxt schema update app.py marinauv run python seed.py marinauv run pxt service run app.py marina --port 8000
Related apps
- Forge Heat CyclesForge heat-cycle registry API: B-tree indexes, chained risk UDFs, and parallel shop-floor writersShares: UDFs
- Climbing Route ToposClimbing-route topo registry API: photo uploads with thumbnails, grayscale copies, grade bands and index-backed crag lookupsShares: UDFs
- Warehouse Pick ListsWarehouse pick-list REST API: units, pick zones, waves and tote labels as incremental computed columns over Json order linesShares: UDFs