Crash course: Python developer, new to the web¶
You can write Python; you have never built a web page. This page teaches the four web concepts you need, shows how Rational Web expresses each one in Python, and ends with a working app you wrote while reading. Nothing here requires knowing HTML, CSS or JavaScript first.
What actually happens when someone visits your site¶
Their browser asks your server for an address, like
GET /profile.Your server runs your Python code and produces a page: HTML, the text-and-structure format browsers render.
The browser draws it. If the page needs to react to clicks, a very small script (Rational Web ships it for you) tells your server “the user clicked this”, and your Python runs again.
That’s the loop: browser asks, Python answers. Everything below is a variation on it.
Concept 1 — Pages: code that answers an address¶
from rational import App, Heading, Page, Text
app = App(title="My site")
@app.page("/")
class Home(Page):
def render(self):
return Heading("Hello, world", level=1)
@app.page("/user/{name}") # /user/ada, /user/grace, ...
class Profile(Page):
name: str # validated from the URL
def render(self):
return Heading(f"Hello, {self.name}", level=1)
if __name__ == "__main__":
app.run() # run: python app.py --dev
render() returns the page’s content as Python objects — Heading, Text, Button.
The framework turns them into HTML. There is one object per HTML building block; you learn them
as you need them, and View page source in the browser always shows you what your objects
became.
Concept 2 — Interactivity: Python functions called by clicks¶
A page that just displays is done: it ships zero JavaScript. To react to the user, connect an event handler — a normal method, but it runs on your server when the user acts:
from rational import Button, Column, Page, State, Text
@app.page("/")
class Counter(Page):
count = State(0) # "remember this between clicks"
def increment(self):
self.count += 1
def render(self):
return Column(
Text(f"Count: {self.count}"),
Button("Add one", on_click=self.increment),
)
State is the memory of the page. When a handler changes it, the parts of the page that used
it are re-rendered on the server and updated in the browser — focus and typing are preserved.
You never write the update step; assigning to State is the whole job.
Forms work the same way, and their input is checked before your code sees it:
from pydantic import BaseModel, Field
class JoinForm(BaseModel):
name: str = Field(min_length=1, max_length=40)
# inside a page:
# Form(Input("Your name", name="name"), Button("Join", type="submit"),
# on_submit=self.join)
async def join(self, form: JoinForm):
... # form.name is a valid, trimmed string — or the user saw a message already
Concept 3 — Remembering things: the database¶
Visitors come back; pages forget. Data you keep between requests lives in a database — you talk to it with SQLAlchemy, and Rational Web wraps the async parts:
# models/database.py — one engine for the whole app
from rational.backend import Database
database = Database("sqlite+aiosqlite:///app.db")
# models/entry.py — a table is a class; a row is an instance
class Entry(database.Base):
id: Mapped[int] = mapped_column(primary_key=True)
text: Mapped[str] = mapped_column(String(280))
Then a service — your rules, in one place — reads and writes it:
from rational.backend import Service, remote
class GuestbookService(Service):
@remote(method="GET")
async def entries(self) -> list[Entry]:
"""Every entry, newest first."""
...
Pages call services through self.use(GuestbookService); loading data belongs in
async def mount(self), which runs before the first render:
class Home(Page):
entries = State(factory=list)
async def mount(self):
self.entries = await self.use(GuestbookService).entries()
Concept 4 — Making it look right: styles¶
CSS (the web’s styling language) is expressed here as Style values — Python objects,
composed with |:
from rational import Style
CARD = Style(padding="md", shadow="lg") | Style(border_left="4px solid var(--rw-color-primary)")
Card(..., style=CARD)
Named sizes ("md", "lg"), theme colours, viewport={"narrow": ...} for phones — the
framework compiles clean CSS from it and reuses what it has already emitted. Start with the
default theme; restyle later by changing values, not by learning a stylesheet language first.
Your first app, in one file¶
# app.py — run with: python app.py --dev
from rational import App, Button, Card, Column, Heading, Input, Page, State, Text
app = App(title="Notes")
@app.page("/")
class Home(Page):
notes = State(factory=list)
def add(self, value: str): # wired to the input; runs on the server
self.notes = [*self.notes, value]
def render(self):
return Column(
Heading("My notes", level=1),
Card(
Input("New note", on_input=lambda v: None), # display only, see below
Button("Add", on_click=lambda: self.add("first note")),
),
*[Text(n) for n in self.notes],
max_width=560,
)
if __name__ == "__main__":
app.run()
Save it, run python app.py --dev, open http://127.0.0.1:8000. Edit the file: the server
restarts and the browser reloads by itself; errors are shown with the failing line of your code
and a hint. When it works, replace the input-and-button with the Form pattern above to get
validation, then follow the tutorial to add the database.
Words you’ll meet¶
HTMLThe text format pages are written in; you produce it through Python objects.
routeAn address (
/,/user/ada) and the code that answers it.request / responseOne browser question and your server’s answer.
sessionThe server’s memory of one visitor (“who is signed in”), keyed by a cookie the browser returns automatically. Rational Web creates and protects it for you.
APIYour service methods, callable as JSON over HTTP — free, documented at
/api/docs.CSSThe language of visual style; here, values you pass as
style=.
Where to go next¶
Tutorial: build a guestbook — the guestbook, step by step, from this file to a real project.
Components, state and events and Styling and themes — the full component and style catalogs.
Examples — ten complete applications, explained file by file.
counterandtodosare the natural second and third things to read.Security model — what the framework already protects you from, and what’s left to you.