Skip to content

Commit

Permalink
added explantion and short demo of APIRouter in action
Browse files Browse the repository at this point in the history
  • Loading branch information
ohmeow committed Dec 4, 2024
1 parent 7d1434f commit b921512
Showing 1 changed file with 133 additions and 29 deletions.
162 changes: 133 additions & 29 deletions nbs/ref/handlers.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,12 @@
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\">\n",
"<script src=\"https://unpkg.com/htmx.org@next/dist/htmx.min.js\"></script><script src=\"https://cdn.jsdelivr.net/gh/answerdotai/[email protected]/fasthtml.js\"></script><script src=\"https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js\"></script><script src=\"https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js\"></script><script>\n",
" function sendmsg() {\n",
" window.parent.postMessage({height: document.documentElement.offsetHeight}, &#x27;*&#x27;);\n",
" window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');\n",
" }\n",
" window.onload = function() {\n",
" sendmsg();\n",
" document.body.addEventListener(&#x27;htmx:afterSettle&#x27;, sendmsg);\n",
" document.body.addEventListener(&#x27;htmx:wsAfterMessage&#x27;, sendmsg);\n",
" document.body.addEventListener('htmx:afterSettle', sendmsg);\n",
" document.body.addEventListener('htmx:wsAfterMessage', sendmsg);\n",
" };</script> </head>\n",
" <body>\n",
" <h1>bar</h1>\n",
Expand Down Expand Up @@ -678,7 +678,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/jhoward/Documents/GitHub/fasthtml/fasthtml/core.py:185: UserWarning: `nope has no type annotation and is not a recognised special name, so is ignored.\n",
"/Users/wgilliam/development/projects/aai/fasthtml/fasthtml/core.py:188: UserWarning: `nope has no type annotation and is not a recognised special name, so is ignored.\n",
" if arg!='resp': warn(f\"`{arg} has no type annotation and is not a recognised special name, so is ignored.\")\n"
]
},
Expand Down Expand Up @@ -1252,12 +1252,12 @@
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\">\n",
"<script src=\"https://unpkg.com/htmx.org@next/dist/htmx.min.js\"></script><script src=\"https://cdn.jsdelivr.net/gh/answerdotai/[email protected]/fasthtml.js\"></script><script src=\"https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js\"></script><script src=\"https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js\"></script><script>\n",
" function sendmsg() {\n",
" window.parent.postMessage({height: document.documentElement.offsetHeight}, &#x27;*&#x27;);\n",
" window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');\n",
" }\n",
" window.onload = function() {\n",
" sendmsg();\n",
" document.body.addEventListener(&#x27;htmx:afterSettle&#x27;, sendmsg);\n",
" document.body.addEventListener(&#x27;htmx:wsAfterMessage&#x27;, sendmsg);\n",
" document.body.addEventListener('htmx:afterSettle', sendmsg);\n",
" document.body.addEventListener('htmx:wsAfterMessage', sendmsg);\n",
" };</script> </head>\n",
" <body>\n",
" <h1>hi</h1>\n",
Expand Down Expand Up @@ -1288,6 +1288,113 @@
"- `(Meta(property='image'), Meta(property='site_name'))` defines two meta tags, which are both placed in the head."
]
},
{
"cell_type": "markdown",
"id": "403fcae3",
"metadata": {},
"source": [
"## APIRouter"
]
},
{
"cell_type": "markdown",
"id": "f8138c07",
"metadata": {},
"source": [
"`APIRouter` is useful when you want to split your application routes across multiple `.py` files that are part of a single FastHTMl application. It accepts an optional `prefix` argument that will be applied to all routes within that instance of `APIRouter`.\n",
"\n",
"Below we define several hypothetical product related routes in a `products.py` and then demonstrate how they can seamlessly be incorporated into a FastHTML app instance."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5988523d",
"metadata": {},
"outputs": [],
"source": [
"# products.py\n",
"ar = APIRouter(prefix=\"/products\")\n",
"\n",
"@ar(\"/all\")\n",
"def all_products(req):\n",
" return Div(\n",
" \"Welcome to the Products Page! Click the button below to look at the details for product 42\",\n",
" Div(\n",
" Button(\n",
" \"Details\",\n",
" hx_get=req.url_for(\"details\", pid=42),\n",
" hx_target=\"#products_list\",\n",
" hx_swap=\"outerHTML\",\n",
" ),\n",
" ),\n",
" id=\"products_list\",\n",
" )\n",
"\n",
"\n",
"@ar.get(\"/{pid}\", name=\"details\")\n",
"def details(pid: int):\n",
" return f\"Here are the product details for ID: {pid}\""
]
},
{
"cell_type": "markdown",
"id": "c7b2325a",
"metadata": {},
"source": [
"Since we specified the `prefix=/products` in our hypothetical `products.py` file, all routes defined in that file will be found under `/products`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "001ff0b8",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"/products/all\n",
"/products/{pid}\n"
]
}
],
"source": [
"print(str(ar.rt_funcs.all_products))\n",
"print(str(ar.rt_funcs.details))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "49795185",
"metadata": {},
"outputs": [],
"source": [
"# main.py\n",
"# from products import ar\n",
"\n",
"app, rt = fast_app()\n",
"ar.to_app(app)\n",
"\n",
"@rt\n",
"def index():\n",
" return Div(\n",
" \"Click me for a look at our products\",\n",
" hx_get=ar.rt_funcs.all_products,\n",
" hx_swap=\"outerHTML\",\n",
" )"
]
},
{
"cell_type": "markdown",
"id": "7eb1a33f",
"metadata": {},
"source": [
"Note how you can reference our python route functions via `APIRouter.rt_funcs` in your `hx_{http_method}` calls like normal."
]
},
{
"cell_type": "markdown",
"id": "311ca66a",
Expand All @@ -1306,14 +1413,14 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Alexis\n",
"Missing required field: username\n"
"404 Not Found\n",
"404 Not Found\n"
]
},
{
"data": {
"text/plain": [
"<Response [400 Bad Request]>"
"<Response [404 Not Found]>"
]
},
"execution_count": null,
Expand Down Expand Up @@ -1353,7 +1460,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"unknown name\n"
"404 Not Found\n"
]
}
],
Expand Down Expand Up @@ -1383,7 +1490,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{\"a\":1,\"b\":\"foo\",\"nm\":\"me\"}\n"
"404 Not Found\n"
]
}
],
Expand Down Expand Up @@ -1422,7 +1529,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{\"a\":\"1\",\"b\":\"foo\"}\n"
"404 Not Found\n"
]
}
],
Expand Down Expand Up @@ -1454,7 +1561,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{\"a\":\"1\",\"b\":\"foo\"}\n"
"404 Not Found\n"
]
}
],
Expand Down Expand Up @@ -1486,7 +1593,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{\"a\":1,\"b\":\"foo\"}\n"
"404 Not Found\n"
]
}
],
Expand Down Expand Up @@ -1518,7 +1625,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"a: 1; b: foo\n"
"404 Not Found\n"
]
}
],
Expand Down Expand Up @@ -1552,10 +1659,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
" <title>It worked!</title>\n",
"<main class=\"container\"> <h1>It worked!</h1>\n",
" <p>15, Lorem</p>\n",
"</main>\n"
"404 Not Found\n"
]
}
],
Expand Down Expand Up @@ -1599,13 +1703,13 @@
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
"404 Not Found\n"
]
},
{
"data": {
"text/plain": [
"'Cookie was set at time 14:16:57.084240'"
"'404 Not Found'"
]
},
"execution_count": null,
Expand Down Expand Up @@ -1647,7 +1751,7 @@
{
"data": {
"text/plain": [
"HttpHeader(k='set-cookie', v='now=\"2024-10-24 14:16:57.121212\"; Path=/; SameSite=lax')"
"HttpHeader(k='set-cookie', v='now=\"2024-12-04 13:45:24.154187\"; Path=/; SameSite=lax')"
]
},
"execution_count": null,
Expand Down Expand Up @@ -1689,13 +1793,13 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Set to 2024-10-24 14:16:57.168313\n"
"Set to 2024-12-04 13:45:24.159764\n"
]
},
{
"data": {
"text/plain": [
"'Session time: 2024-10-24 14:16:57.168313'"
"'Session time: 2024-12-04 13:45:24.159764'"
]
},
"execution_count": null,
Expand Down Expand Up @@ -1864,7 +1968,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Headers({'access-control-allow-origin': '*', 'access-control-allow-methods': 'POST', 'access-control-allow-headers': '*', 'content-length': '0', 'set-cookie': 'session_=eyJhdXRoIjogIjIwMjQtMTAtMjQgMTQ6MTY6NTcuMTY4MzEzIn0=.ZxnKOQ.8x-zyM5rd59ix3PtADan0qfL-bk; path=/; Max-Age=31536000; httponly; samesite=lax'})\n"
"Headers({'access-control-allow-origin': '*', 'access-control-allow-methods': 'POST', 'access-control-allow-headers': '*', 'content-length': '0', 'set-cookie': 'session_=eyJhdXRoIjogIjIwMjQtMTItMDQgMTM6NDU6MjQuMTU5NzY0In0=.Z1DNdA.GV-NVoOnJeambm9_uE3crhoGH34; path=/; Max-Age=31536000; httponly; samesite=lax'})\n"
]
}
],
Expand Down Expand Up @@ -1913,12 +2017,12 @@
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\">\n",
"<script src=\"https://unpkg.com/htmx.org@next/dist/htmx.min.js\"></script><script src=\"https://cdn.jsdelivr.net/gh/answerdotai/[email protected]/fasthtml.js\"></script><script src=\"https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js\"></script><script src=\"https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js\"></script><script>\n",
" function sendmsg() {\n",
" window.parent.postMessage({height: document.documentElement.offsetHeight}, &#x27;*&#x27;);\n",
" window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');\n",
" }\n",
" window.onload = function() {\n",
" sendmsg();\n",
" document.body.addEventListener(&#x27;htmx:afterSettle&#x27;, sendmsg);\n",
" document.body.addEventListener(&#x27;htmx:wsAfterMessage&#x27;, sendmsg);\n",
" document.body.addEventListener('htmx:afterSettle', sendmsg);\n",
" document.body.addEventListener('htmx:wsAfterMessage', sendmsg);\n",
" };</script> </head>\n",
" <body>\n",
" <div>nope</div>\n",
Expand Down

0 comments on commit b921512

Please sign in to comment.