Version 7.14.2¶
Patch release: a modular per-resource FastAPI backend, and correct deletes, edits and multiplicities in generated web applications. Everything was verified end to end on a hotel-booking model: every generated API route was driven with real data, and the generated React screens were exercised in a browser. No metamodel or API-contract changes — freshly generated applications keep the same REST contract, so existing frontends and deployments are not affected.
Highlights¶
The generated backend is modular:
BackendGeneratornow emits a slimmain_api.py(app setup, middleware, exception handlers, system endpoints) that wires onerouters/<class>.pyper resource, plusdatabase.py(the shared engine/session, honoring theDATABASE_URLenvironment variable) andbal_stdlib.py.RESTAPIGenerator(backend=True)renders the same API layer, and the ~100 KB monolithicmain_api.pytemplate is gone, so the association-class, OCL and method-normalization logic lives in exactly one place. The route table is identical to the previous generator on the reference model. A few behaviors were fixed along the way:/search/endpoints expose real filter parameters (including inherited attributes — the old type check never matched, so every search returned everything), path parameters use the declared type of the primary key, a modeled method without an implementation answers501instead of a fake success,/healthactually queries the database, andsql_alchemy.pysharesDATABASE_URLwith the API, no longer creates tables as an import side effect, and types association-class foreign keys after the referenced primary key.Deleting an entity deletes its association-class links: deleting a
Bookingthat hadReservedRoomrows crashed the generated backend (the link’s foreign key is part of its composite primary key, so SQLAlchemy could neither null it nor knew to delete it). The entity → links relationships now carrycascade="all, delete-orphan"from both ends, andDELETEreturns a snapshot of the deleted row. The generated table also addresses rows by their real key (row_key_fieldsin the data binding): aRoombynumberand a link by both foreign keys (/reservedroom/{booking_id}/{rooms_id}/) — previously it guessed the first column of the row, which for a link was its price.Lower-bound multiplicities are enforced wherever a relationship can shrink: creation already refused a
Bookingwithout guests, but every later path could strip them — editing the booking with an empty list, removing the link, or deleting the lastGuestitself. The ORM cannot express a lower bound on the many side, so the generated routers enforce it: deleting an entity, removing a link (plain or association-class), or editing a relationship list is refused with a409naming the entity and the minimum (Cannot delete Guest 3: Booking 10 requires at least 1 guests), and deleting the target of a mandatory to-one end gets the same message instead of aNOT NULLcrash. Editing the owner of a one-to-many end (Employee.manages) now diffs the current and requested members instead of nulling every foreign key first, which had made such entities impossible to edit at all.Generated edit dialogs are safe and fast: the table fetches the detailed rows whenever its form has a relationship, so the edit dialog opens with the current selections instead of empty ones — a save used to silently detach every relationship of the edited entity — and a relationship the row never carried is left out of the save. An open Add/Edit dialog no longer fires about a thousand lookup requests per second (a memoization loop on tables without explicit columns). A refused delete shows the backend’s reason in a dismissible banner instead of failing silently, inherited attributes (an
Employee’slast_name, defined onPerson) are updated byPUT, and aPUTthat omits a many-to-many list leaves the links untouched instead of crashing.