--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-pagerouters/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.templateslayout.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 detest.css et test.js` à partir du répertoire statique pour les testsstaticFaites 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 denginx` 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