pypi-fastapi

Description
FastAPI framework, high performance, easy to learn, fast to code, ready for production
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/pypi-fastapi@0.116.0

static-templating.md docs/

1
# Static Files and Templating
2
3
FastAPI provides built-in support for serving static files and rendering HTML templates, enabling the creation of full web applications that combine API endpoints with frontend content. This functionality is essential for applications that need to serve HTML pages, CSS, JavaScript, images, and other static assets alongside their API functionality.
4
5
## Capabilities
6
7
### Static Files Serving
8
9
Class for serving static files such as HTML, CSS, JavaScript, images, and other assets from the filesystem.
10
11
```python { .api }
12
class StaticFiles:
13
def __init__(
14
self,
15
*,
16
directory: str = None,
17
packages: List[str] = None,
18
html: bool = False,
19
check_dir: bool = True,
20
follow_symlink: bool = False,
21
) -> None:
22
"""
23
Create static files application for serving static content.
24
25
Parameters:
26
- directory: Directory path containing static files
27
- packages: List of Python packages containing static files
28
- html: Whether to serve HTML files for directory requests
29
- check_dir: Whether to check if directory exists on startup
30
- follow_symlink: Whether to follow symbolic links
31
"""
32
```
33
34
### Jinja2 Template Engine
35
36
Template engine integration for rendering dynamic HTML content with data from your API endpoints.
37
38
```python { .api }
39
class Jinja2Templates:
40
def __init__(self, directory: str) -> None:
41
"""
42
Create Jinja2 templates instance.
43
44
Parameters:
45
- directory: Directory containing template files
46
"""
47
48
def TemplateResponse(
49
self,
50
name: str,
51
context: dict,
52
status_code: int = 200,
53
headers: dict = None,
54
media_type: str = None,
55
background: BackgroundTask = None,
56
) -> TemplateResponse:
57
"""
58
Render template with context data and return as HTTP response.
59
60
Parameters:
61
- name: Template file name
62
- context: Dictionary of template variables
63
- status_code: HTTP status code
64
- headers: Additional HTTP headers
65
- media_type: Response content type
66
- background: Background task to run after response
67
68
Returns:
69
TemplateResponse with rendered HTML content
70
"""
71
72
def get_template(self, name: str) -> Template:
73
"""Get template object by name."""
74
```
75
76
## Usage Examples
77
78
### Serving Static Files
79
80
```python
81
from fastapi import FastAPI
82
from fastapi.staticfiles import StaticFiles
83
84
app = FastAPI()
85
86
# Mount static files directory
87
app.mount("/static", StaticFiles(directory="static"), name="static")
88
89
# Mount static files with HTML serving
90
app.mount("/public", StaticFiles(directory="public", html=True), name="public")
91
92
# Serve from Python package
93
app.mount("/assets", StaticFiles(packages=["mypackage"]), name="assets")
94
```
95
96
With this setup:
97
- Files in `./static/` are accessible at `/static/filename.ext`
98
- Files in `./public/` are accessible at `/public/filename.ext`
99
- Directory requests to `/public/` will serve `index.html` if `html=True`
100
- Package assets are served from installed Python packages
101
102
### HTML Template Rendering
103
104
```python
105
from fastapi import FastAPI, Request
106
from fastapi.templating import Jinja2Templates
107
from fastapi.responses import HTMLResponse
108
109
app = FastAPI()
110
templates = Jinja2Templates(directory="templates")
111
112
@app.get("/", response_class=HTMLResponse)
113
async def home(request: Request):
114
return templates.TemplateResponse(
115
"index.html",
116
{"request": request, "title": "Home Page"}
117
)
118
119
@app.get("/user/{user_id}", response_class=HTMLResponse)
120
async def user_profile(request: Request, user_id: int):
121
# Simulate user data retrieval
122
user_data = {"id": user_id, "name": f"User {user_id}"}
123
return templates.TemplateResponse(
124
"profile.html",
125
{
126
"request": request,
127
"user": user_data,
128
"title": f"Profile - {user_data['name']}"
129
}
130
)
131
```
132
133
Template file `templates/index.html`:
134
135
```html
136
<!DOCTYPE html>
137
<html>
138
<head>
139
<title>{{ title }}</title>
140
<link rel="stylesheet" href="/static/style.css">
141
</head>
142
<body>
143
<h1>Welcome to FastAPI</h1>
144
<p>This is a template-rendered page.</p>
145
<script src="/static/script.js"></script>
146
</body>
147
</html>
148
```
149
150
Template file `templates/profile.html`:
151
152
```html
153
<!DOCTYPE html>
154
<html>
155
<head>
156
<title>{{ title }}</title>
157
</head>
158
<body>
159
<h1>User Profile</h1>
160
<p>ID: {{ user.id }}</p>
161
<p>Name: {{ user.name }}</p>
162
<a href="/">Back to Home</a>
163
</body>
164
</html>
165
```
166
167
### Complete Web Application Example
168
169
```python
170
from fastapi import FastAPI, Request, Form
171
from fastapi.templating import Jinja2Templates
172
from fastapi.staticfiles import StaticFiles
173
from fastapi.responses import HTMLResponse, RedirectResponse
174
from typing import Optional
175
176
app = FastAPI()
177
178
# Mount static files for CSS, JS, images
179
app.mount("/static", StaticFiles(directory="static"), name="static")
180
181
# Setup templates
182
templates = Jinja2Templates(directory="templates")
183
184
# In-memory storage for demo
185
items = []
186
187
@app.get("/", response_class=HTMLResponse)
188
async def home(request: Request):
189
return templates.TemplateResponse(
190
"home.html",
191
{"request": request, "items": items}
192
)
193
194
@app.get("/add", response_class=HTMLResponse)
195
async def add_item_form(request: Request):
196
return templates.TemplateResponse(
197
"add_item.html",
198
{"request": request}
199
)
200
201
@app.post("/add")
202
async def add_item(
203
request: Request,
204
name: str = Form(...),
205
description: str = Form(...)
206
):
207
item = {"id": len(items) + 1, "name": name, "description": description}
208
items.append(item)
209
return RedirectResponse(url="/", status_code=303)
210
211
@app.get("/item/{item_id}", response_class=HTMLResponse)
212
async def item_detail(request: Request, item_id: int):
213
item = next((item for item in items if item["id"] == item_id), None)
214
if not item:
215
return templates.TemplateResponse(
216
"404.html",
217
{"request": request},
218
status_code=404
219
)
220
return templates.TemplateResponse(
221
"item_detail.html",
222
{"request": request, "item": item}
223
)
224
225
# API endpoints for AJAX/SPA integration
226
@app.get("/api/items")
227
async def api_get_items():
228
return {"items": items}
229
230
@app.post("/api/items")
231
async def api_add_item(item: dict):
232
new_item = {"id": len(items) + 1, **item}
233
items.append(new_item)
234
return new_item
235
```
236
237
### Template with Custom Filters
238
239
```python
240
from fastapi import FastAPI, Request
241
from fastapi.templating import Jinja2Templates
242
import datetime
243
244
app = FastAPI()
245
templates = Jinja2Templates(directory="templates")
246
247
# Add custom filter to templates
248
def format_datetime(value):
249
return value.strftime("%Y-%m-%d %H:%M:%S")
250
251
templates.env.filters["datetime"] = format_datetime
252
253
@app.get("/dashboard", response_class=HTMLResponse)
254
async def dashboard(request: Request):
255
return templates.TemplateResponse(
256
"dashboard.html",
257
{
258
"request": request,
259
"current_time": datetime.datetime.now(),
260
"data": {"users": 150, "posts": 1240}
261
}
262
)
263
```
264
265
Template using custom filter:
266
267
```html
268
<!DOCTYPE html>
269
<html>
270
<head>
271
<title>Dashboard</title>
272
</head>
273
<body>
274
<h1>Dashboard</h1>
275
<p>Current time: {{ current_time | datetime }}</p>
276
<p>Users: {{ data.users }}</p>
277
<p>Posts: {{ data.posts }}</p>
278
</body>
279
</html>
280
```
281
282
### Error Page Templates
283
284
```python
285
from fastapi import FastAPI, Request, HTTPException
286
from fastapi.templating import Jinja2Templates
287
from fastapi.responses import HTMLResponse
288
289
app = FastAPI()
290
templates = Jinja2Templates(directory="templates")
291
292
@app.exception_handler(404)
293
async def not_found_handler(request: Request, exc: HTTPException):
294
return templates.TemplateResponse(
295
"404.html",
296
{"request": request},
297
status_code=404
298
)
299
300
@app.exception_handler(500)
301
async def server_error_handler(request: Request, exc: HTTPException):
302
return templates.TemplateResponse(
303
"500.html",
304
{"request": request},
305
status_code=500
306
)
307
```
308
309
## Types
310
311
```python { .api }
312
from typing import Any, Dict, List, Optional
313
from starlette.responses import Response
314
from starlette.background import BackgroundTask
315
from starlette.templating import _TemplateResponse as TemplateResponse
316
from jinja2 import Template, Environment
317
318
# Template response type
319
TemplateResponse = _TemplateResponse
320
321
# Jinja2 environment type
322
Jinja2Environment = Environment
323
324
# Template context type
325
TemplateContext = Dict[str, Any]
326
```