mirror of https://github.com/tiangolo/fastapi.git
✨ Add docs and tests for Jinja2 templates (#186)
* ✨ Add docs and tests for Jinja2 templates * 🎨 Fix format in test, remove unused import
This commit is contained in:
parent
0cd5485597
commit
c1df0f6b84
|
|
@ -0,0 +1,6 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from starlette.staticfiles import StaticFiles
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
h1 {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Item Details</title>
|
||||||
|
<link href="{{ url_for('static', path='/styles.css') }}" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Item ID: {{ id }}</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from starlette.requests import Request
|
||||||
|
from starlette.staticfiles import StaticFiles
|
||||||
|
from starlette.templating import Jinja2Templates
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||||
|
|
||||||
|
|
||||||
|
templates = Jinja2Templates(directory="templates")
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/{id}")
|
||||||
|
async def read_item(request: Request, id: str):
|
||||||
|
return templates.TemplateResponse("item.html", {"request": request, "id": id})
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
You can serve static files automatically from a directory using <a href="https://www.starlette.io/staticfiles/" target="_blank">Starlette's Static Files</a>.
|
||||||
|
|
||||||
|
## Install `aiofiles`
|
||||||
|
|
||||||
|
First you need to install `aiofiles`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install aiofiles
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use `StaticFiles`
|
||||||
|
|
||||||
|
* Import `StaticFiles` from Starlette.
|
||||||
|
* "Mount" it the same way you would <a href="https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/" target="_blank">mount a Sub-Application</a>.
|
||||||
|
|
||||||
|
```Python hl_lines="2 6"
|
||||||
|
{!./src/static_files/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you could have a directory `./static/` with some files that will be served directly.
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
The first `"/static"` refers to the sub-path this "sub-application" will be "mounted" on. So, any path that starts with `"/static"` will be handled by it.
|
||||||
|
|
||||||
|
The `directory="static"` refers to the name of the directory that contains your static files.
|
||||||
|
|
||||||
|
The `name="static"` gives it a name that can be used internally by **FastAPI**.
|
||||||
|
|
||||||
|
All these parameters can be different than "`static`", adjust them with the needs and specific details of your own application.
|
||||||
|
|
||||||
|
## More info
|
||||||
|
|
||||||
|
For more details and options check <a href="https://www.starlette.io/staticfiles/" target="_blank">Starlette's docs about Static Files</a>.
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
You can use any template engine you want with **FastAPI**.
|
||||||
|
|
||||||
|
A common election is Jinja2, the same one used by Flask and other tools.
|
||||||
|
|
||||||
|
Starlette has utilities to configure it easily that you can use directly in your **FastAPI** application.
|
||||||
|
|
||||||
|
## Install dependencies
|
||||||
|
|
||||||
|
Install `jinja2`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install jinja2
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to also serve static files (as in this example), install `aiofiles`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install aiofiles
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using `Jinja2Templates`
|
||||||
|
|
||||||
|
* Import `Jinja2Templates` form Starlette.
|
||||||
|
* Create a `templates` object that you can re-use later.
|
||||||
|
* Declare a `Request` parameter in the *path operation* that will return a template.
|
||||||
|
* Use the `templates` you created to render and return a `TemplateResponse`, passing the `request` as one of the key-value pairs in the Jinja2 "context".
|
||||||
|
|
||||||
|
```Python hl_lines="4 11 15 16"
|
||||||
|
{!./src/templates/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
Notice that you have to pass the `request` as part of the key-value pairs in the context for Jinja2. So, you also have to declare it in your *path operation*.
|
||||||
|
|
||||||
|
## Writing templates
|
||||||
|
|
||||||
|
Then you can write a template at `templates/item.html` with:
|
||||||
|
|
||||||
|
```jinja hl_lines="7"
|
||||||
|
{!./src/templates/templates/item.html!}
|
||||||
|
```
|
||||||
|
|
||||||
|
It will show the `id` taken from the "context" `dict` you passed:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{"request": request, "id": id}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Templates and static files
|
||||||
|
|
||||||
|
And you can also use `url_for()` inside of the template, and use it, for example, with the `StaticFiles` you mounted.
|
||||||
|
|
||||||
|
```jinja hl_lines="4"
|
||||||
|
{!./src/templates/templates/item.html!}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, it would link to a CSS file at `static/styles.css` with:
|
||||||
|
|
||||||
|
```CSS hl_lines="4"
|
||||||
|
{!./src/templates/static/styles.css!}
|
||||||
|
```
|
||||||
|
|
||||||
|
And because you are using `StaticFiles`, that CSS file would be served automatically by your **FastAPI** application at the URL `/static/styles.css`.
|
||||||
|
|
||||||
|
## More details
|
||||||
|
|
||||||
|
For more details, including how to test templates, check <a href="https://www.starlette.io/templates/" target="_blank">Starlette's docs on templates</a>.
|
||||||
|
|
@ -73,6 +73,8 @@ nav:
|
||||||
- Background Tasks: 'tutorial/background-tasks.md'
|
- Background Tasks: 'tutorial/background-tasks.md'
|
||||||
- Sub Applications - Behind a Proxy: 'tutorial/sub-applications-proxy.md'
|
- Sub Applications - Behind a Proxy: 'tutorial/sub-applications-proxy.md'
|
||||||
- Application Configuration: 'tutorial/application-configuration.md'
|
- Application Configuration: 'tutorial/application-configuration.md'
|
||||||
|
- Static Files: 'tutorial/static-files.md'
|
||||||
|
- Templates: 'tutorial/templates.md'
|
||||||
- GraphQL: 'tutorial/graphql.md'
|
- GraphQL: 'tutorial/graphql.md'
|
||||||
- WebSockets: 'tutorial/websockets.md'
|
- WebSockets: 'tutorial/websockets.md'
|
||||||
- 'Events: startup - shutdown': 'tutorial/events.md'
|
- 'Events: startup - shutdown': 'tutorial/events.md'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from starlette.testclient import TestClient
|
||||||
|
|
||||||
|
|
||||||
|
def test_main():
|
||||||
|
shutil.copytree("./docs/src/templates/templates/", "./templates")
|
||||||
|
shutil.copytree("./docs/src/templates/static/", "./static")
|
||||||
|
from templates.tutorial001 import app
|
||||||
|
|
||||||
|
client = TestClient(app)
|
||||||
|
response = client.get("/items/foo")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert b"<h1>Item ID: foo</h1>" in response.content
|
||||||
|
response = client.get("/static/styles.css")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert b"color: green;" in response.content
|
||||||
|
shutil.rmtree("./templates")
|
||||||
|
shutil.rmtree("./static")
|
||||||
Loading…
Reference in New Issue