Page
A Page is the value a route returns: the new state plus a list of
everything to show. Drafter renders the list top to bottom, replacing
whatever page was on screen before.
Syntax
Page(state, content)
Page(content)
| Parameter | Type | Meaning |
|---|---|---|
state |
any | The state to carry forward, almost always your State dataclass. When you pass only one argument, the state is None. |
content |
list |
A list of strings and components, rendered in order. Must be a list, even for a single item. |
Two more parameters, css and js, accept raw CSS and JavaScript to
inject when the page renders. They are for advanced use; see
JavaScript interop.
With state and without
An app with a State dataclass passes it as the first argument, so the
next route receives the current values:
from drafter import *
from dataclasses import dataclass
@dataclass
class State:
visits: int
@route
def index(state: State) -> Page:
state.visits = state.visits + 1
return Page(state, [
"Visits so far: " + str(state.visits) + "\n",
Button("Visit again", "index")
])
start_server(State(0))
An app with nothing to remember can skip state entirely:
from drafter import *
@route
def index() -> Page:
return Page([
"This site remembers nothing.\n",
Link("See for yourself", "again")
])
@route
def again() -> Page:
return Page([
"Still nothing remembered.\n",
Link("Back", "index")
])
start_server()
What content can hold
Each item in the content list is either a string or a component:
- Strings render as text. Drafter does not add line breaks between
items; end a string with
"\n"where you want the next item to start on a new line. - Components (
Button,TextBox,Header,Image, and the rest of the component list) render as their HTML.
A single string or component is quietly wrapped in a list for you, but
anything else (a number, a dataclass, a list of lists) produces a
friendly error that names the route that returned it. The most common
mistake is forgetting str() around a number. See
Page content must be a list.
What Drafter verifies
Before showing a page, Drafter checks it:
- Links and buttons must point somewhere real. A
ButtonorLinkwhose target names no existing route stops the page with a points to non-existent page error, rather than rendering a dead control. - Input names should be unique. Two form components with the same
nameon one page would both try to fill the same parameter; see Two components share a name.
Notes
- A route builds a fresh
Pageevery time it runs. Pages are descriptions of a screen, not the screen itself; returning the samePagetwice renders the same thing twice. - Routes can call other routes that return a
Page. Ending a route withreturn index(state)is the standard way to show the front page after making a change. - In tests, compare pages directly:
assert_has(index(State(0)), Button("Visit again", "index")). See Test a feature.
Related
- route: how a function comes to return pages.
- Fragment, Update, Redirect: the other values a route can return.
- Routes and pages: the concept behind the machinery.