Admin CRUD Interface
Website Rebuild with Astro
Chapter 10 · Admin CRUD Interface
Django has a free admin. Laravel and Rails don't, but each has some code-generation help — Laravel's make:model -mcr, Rails' own rails generate scaffold. Astro has neither. This is genuinely the most minimal starting point of all five siblings.
The Parent Picker
The same searchable flat list every sibling course reached for — every other page's own fullPath, filterable client-side, rather than a nested tree widget, for the same scale-justified reason established since the Next.js rebuild's own Chapter 10.
Paying Off Chapter 2's Deferred Cost
Chapter 2 already established that Drizzle has no lifecycle hooks — so updateDescendantPaths is a fully explicit recursive walk, no different in spirit from Laravel's own updateDescendantPaths() or Rails' own update_descendant_paths!, just written without any framework callback machinery underneath it at all.
Delete Refusal — a Precise Callback to Two Earlier Findings
onDelete: 'restrict' as a genuine database-level constraint, the same layer Laravel's own restrictOnDelete() operates at. That means deleting a page with children here raises a real, raw database exception — requiring the same try/catch ceremony Laravel's own Chapter 10 needed, not the smoother built-in error-population Rails found for itself.
PROTECT is application-level, yet it still raises a real ProtectedError exception that needs its own try/except. Rails' own smoother, non-exception path — destroy simply returning false with errors already populated — was a specific design choice in ActiveRecord's own API, not a trait every application-level protection shares. Astro needs a try/catch for the same reason Laravel and Django both effectively do, each for their own reason.
Five Admin Interfaces, Compared
| Django | Laravel | Rails | Astro | |
|---|---|---|---|---|
| Free admin? | Yes — live, runtime-introspected | No | No | No |
| Scaffold generator? | N/A — has the admin instead | make:model -mcr | rails generate scaffold | None at all |
| Delete-with-children handling | Caught ProtectedError | Caught QueryException | Returns false, no exception | Caught raw database exception |
Hands-On Exercises
Build the searchable flat parent picker for the admin interface, excluding the page itself from its own candidate-parent list.
📄 View solutionBuild movePage() and updateDescendantPaths(), and confirm a real reparent operation correctly cascades full_path updates to every descendant, not just the moved page itself.
📄 View solutionAttempt to delete a page with children via the DELETE endpoint, confirm the raw database constraint throws, and confirm the try/catch turns it into a real 409 response with a readable message.
📄 View solutionChapter 10 Quick Reference
- No free admin, no scaffold generator — the most minimal starting point of all five siblings
movePage()/updateDescendantPaths()— fully explicit, since Drizzle has no lifecycle hooks- Delete refusal needs a real
try/catch— the same ceremony as Laravel, and precisely, as Django too - A corrected rule — Rails' own smooth path was ActiveRecord's own API design, not a universal application-level trait
- Next chapter: Deployment