--Jinja2
pour la fonction Template nécessite une installation supplémentaire de ʻaiofilespour fournir des fichiers statiques --Référence: [Document officiel](https://fastapi.tiangolo.com/advanced/templates/#install-dependencies) --Ajout de ce qui suit à
pyproject.toml`
pyproject.toml(Ajouts)
[tool.poetry.dependencies]
#Ajout des deux suivants
jinja2 = "*"
aiofiles = "*"
Au total, par exemple:
pyproject.toml
[tool.poetry]
name = "test_fastapi_app"
version = "0.1.0"
description = "just for test"
authors = ["Your Name <[email protected]>"]
[tool.poetry.dependencies]
python = "^3.8"
uvicorn = "*"
fastapi = "*"
jinja2 = "*"
aiofiles = "*"
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
$ tree
.
├── app
│ ├── Dockerfile
│ ├── app
│ │ ├── __init__.py
│ │ ├── main.py
│ │ ├── routers
│ │ │ ├── __init__.py
│ │ │ └── subpage.py
│ │ ├── static
│ │ │ ├── layout.css
│ │ │ └── subpage
│ │ │ ├── test.css
│ │ │ └── test.js
│ │ └── templates
│ │ ├── layout.html
│ │ └── subpage
│ │ └── index.html
│ ├── poetry.lock
│ └── pyproject.toml
├── docker-compose.yml
└── web
Puisque les fichiers dans ʻapp / app` ont été modifiés / ajoutés, nous regarderons les détails ci-dessous.
main.py
--Correction du contenu comme suit
main.py
"""
app main
"""
import pathlib
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.responses import RedirectResponse
from .routers import subpage
# pathlib.Obtenez le chemin absolu d'un répertoire statique à l'aide de Path
PATH_STATIC = str(pathlib.Path(__file__).resolve().parent / "static")
def create_app():
"""
create app
-Ça devient un peu compliqué, donc c'est fonctionnalisé
"""
_app = FastAPI()
#Module sous-application des routeurs`subpage`URL"/subpage/"Monter ci-dessous
_app.include_router(
subpage.router,
prefix="/subpage",
tags=["subpage"],
responses={404: {"description": "not found"}},
)
# static
# URL`/static"Montez le fichier statique ci-dessous
_app.mount(
"/static",
StaticFiles(directory=PATH_STATIC, html=False),
name="static",
)
return _app
app = create_app()
@app.get('/')
async def redirect_subpage():
"""redirect webpage"""
return RedirectResponse( #Redirection vers une page Web créée avec une sous-application de sous-page
"/subpage",
)
Le nombre de lignes a un peu augmenté, mais je fais principalement
sous-page
routers/subpage.py
__Init __. Py
au même emplacement est un fichier viderouters/subpage.py
"""
test subpage
"""
import pathlib
from fastapi import (
APIRouter,
Request,
)
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
#Obtenez le chemin absolu du répertoire des modèles
PATH_TEMPLATES = str(
pathlib.Path(__file__).resolve() \
.parent.parent / "templates"
)
#Génération d'objets Jinja2
templates = Jinja2Templates(directory=PATH_TEMPLATES)
#Sous application
router = APIRouter()
@router.get("/", response_class=HTMLResponse)
async def site_root(
request: Request,
):
"""test subpage"""
title = "test subpage"
return templates.TemplateResponse(
"subpage/index.html", # `templates`Chemin relatif dans le répertoire
context={ #Les variables peuvent être transmises au format dict
"request": request,
"title": title,
}
)
templates
et renvoyez-le sous forme de réponse HTML.templates
layout.html
layout.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<meta name="apple-mobile-web-app-capable" content="yes">
{% if title %}
<title>{{ title }}</title>
{% else %}
<title>Template</title>
{% endif %}
<!-- jQuery & Bootstrap4 -->
<script
src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous"></script>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous">
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
<!-- jQuery UI -->
<script
src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
crossorigin="anonymous"></script>
<link
rel="stylesheet"
type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.min.css">
<!-- CUSTOM STYLE -->
<link rel="stylesheet" type="text/css" href="{{url_for('static', path='/layout.css')}}">
{% block head %}{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
--Chargement de jQuery
, jQuery-UI
, Bootstrap
--title
est reçu comme paramètre
layout.css
à partir d'un répertoire statique en utilisant ʻurl_for` de Jinja2 pour testersubpage/index.html
subpage/index.html
{% extends "layout.html" %}
{% block head %}
<link
rel="stylesheet"
type="text/css"
href="{{ url_for('static', path='/subpage/test.css') }}">
<script
type="text/javascript"
src="{{ url_for('static', path='subpage/test.js') }}"></script>
{% endblock %}
{% block content %}
<h2>Test Subpage</h2>
<br>
<h3>
Hello, World.
</h3>
{% endblock %}
layout.html
ʻextendset en recevant les paramètres nécessaires du côté Fast API. --Chargement de
test.css et
test.js` à partir du répertoire statique pour les testsstatic
Faites ce qui suit
#Package ajouté, source modifiée / ajoutée, donc reconstruire
docker-compose build
#Démarrage du service
docker-compose up -d
Si vous exécutez dans un environnement local, jetez un œil à http: // localhost
À première vue, cela semble fonctionner, mais si vous regardez de près, vous ne pouvez pas lire le fichier static
à partir du HTML:
<link rel="stylesheet" type="text/css" href="http://backend/static/layout.css">
<link
rel="stylesheet"
type="text/css"
href="http://backend/static/subpage/test.css">
<script
type="text/javascript"
src="http://backend/static/subpage/test.js"></script>
src
et href
soithttp: // localhost / <url>
dans ce cas, mais comme ↑,http: // backend / <url>
changer en** dans le ** code FastAPI ** (
main.py,
routers / ***. Py`, etc.)Puisqu'il y a un problème de proxy dans ce domaine, il est nécessaire de modifier l'option de démarrage de ʻuvicornet le paramètre de
nginx` pour y faire face.
4-1. uvicorn
--Si vous faites de votre mieux pour lire les parties déploiement et setting de l'officiel uvicorn, `- Il semble que l'option des en-têtes de proxy doit être définie
En conclusion, changez le CMD
du Dockerfile comme suit pour corriger l'option de démarrage de ʻuvicorn`
Dockerfile (correction)
# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0"]
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--proxy-headers", "--forwarded-allow-ips", "*"]
4-2. Nginx
Ensuite, modifiez le fichier de configuration Nginx (web / conf.d / app.conf
)
(Voir le [déploiement] d'uvicorn (https://www.uvicorn.org/deployment/) pour un exemple de Nginx)
$ tree
.
├── app
├── docker-compose.yml
└── web
└── conf.d
└── app.conf
-Modifier ʻapp.conf` dans ↑ comme suit
location /
:conf:conf.d/app.conf
upstream backend {
server app:8000;
}
server {
listen 80;
# server_name localhost;
# index index.html index.htm;
location / {
#Ajout des 5 éléments suivants
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_buffering off;
proxy_pass http://backend;
}
# log
# access_log /var/log/nginx/access.log;
# error_log /var/log/nginx/error.log;
}
# server_tokens off;
Si vous faites jusqu'ici, l'URL que vous attendiez sera appelée correctement comme http: // localhost / <url>
même si vous avez fait ʻurl_for` sur le fichier HTML.
--FastAPI + uvicorn + Nginx (docker-compose) configuration pour créer une fonction web avec l'atmosphère de Flask --Flask est plus facile à utiliser lors de la création de fonctions Web à l'aide de la fonction Template, etc., et j'ai trouvé que c'était plus facile car il y a beaucoup de documents. --FastAPI est spécialisé pour les fonctions RestAPI et peut ne pas être bon pour les fonctions Web. Cependant, si vous pouvez maîtriser le traitement asynchrone, il peut y avoir un potentiel de performances. --J'ai également fait une conversion SSL (et c'était assez gênant) ~~, donc je prévois d'écrire plus tard ~~
Recommended Posts