Intégration suivante.js pour les projets Django.
Vous souhaitez donc utiliser Django et Next.js dans votre projet. Il y a deux scénarios:
Vous commencez un nouveau projet et vous souhaitez utiliser Django comme back-end et Next.js comme front-end. Django ne sert que les demandes d'API. Tout le code frontal vit dans Next.js et vous n'écrivez aucun modèle Django.
Dans ce scénario, vous n'avez pas besoin de ce package (bien que vous puissiez l'utiliser). Vous commencez simplement à la fois les serveurs Django et Next.js et pointez votre serveur Web public vers Next.js.
Vous avez besoin de modèles Django et de Next.js en même temps et ces pages devraient facilement être liées les unes aux autres. Peut-être que vous avez un projet Django existant qui a des pages rendues par le modèle DJANGO et que vous souhaitez de nouvelles pages dans Next.js. Ou vous souhaitez migrer votre front-end vers Next.js, mais comme le projet est grand, vous devez le faire progressivement.
Dans ce scénario, ce package est pour vous!
À partir d'un commentaire sur stackOverflow:
Exécutez 2 ports sur le même serveur. Un pour Django (face public) et un pour next.js (interne). Laissez Django gérer toutes les demandes Web. Pour chaque demande, interrogez Next.js de Django View pour obtenir une réponse HTML. Renvoyez cette réponse HTML exacte de Django View.
Installez la dernière version de PYPI.
pip install django-nextjs Ajoutez django_nextjs.apps.DjangoNextJSConfig sur INSTALLED_APPS .
Configurez les URL Next.js en fonction de votre environnement.
Si vous servez votre site sous ASGI pendant le développement, utilisez les canaux Django et ajoutez NextJSProxyHttpConsumer , NextJSProxyWebsocketConsumer à asgi.py comme l'exemple suivant.
Remarque: Nous vous recommandons d'utiliser les canaux ASGI et DJANGO, car il est nécessaire pour un actualisation rapide (remplacement du module chaud) de fonctionner correctement dans NextJS 12+.
import os
from django . core . asgi import get_asgi_application
from django . urls import re_path , path
os . environ . setdefault ( "DJANGO_SETTINGS_MODULE" , "myproject.settings" )
django_asgi_app = get_asgi_application ()
from channels . auth import AuthMiddlewareStack
from channels . routing import ProtocolTypeRouter , URLRouter
from django_nextjs . proxy import NextJSProxyHttpConsumer , NextJSProxyWebsocketConsumer
from django . conf import settings
# put your custom routes here if you need
http_routes = [ re_path ( r"" , django_asgi_app )]
websocket_routers = []
if settings . DEBUG :
http_routes . insert ( 0 , re_path ( r"^(?:_next|__next|next).*" , NextJSProxyHttpConsumer . as_asgi ()))
websocket_routers . insert ( 0 , path ( "_next/webpack-hmr" , NextJSProxyWebsocketConsumer . as_asgi ()))
application = ProtocolTypeRouter (
{
# Django's ASGI application to handle traditional HTTP and websocket requests.
"http" : URLRouter ( http_routes ),
"websocket" : AuthMiddlewareStack ( URLRouter ( websocket_routers )),
# ...
}
) Sinon (si vous servez sous WSGI pendant le développement), ajoutez ce qui suit au début de urls.py :
path ( "" , include ( "django_nextjs.urls" )) AVERTISSEMENT: Si vous servez sous ASGI, n'ajoutez pas cela à votre urls.py Cela peut provoquer des blocs de blocage.
En production, utilisez un proxy inversé comme Nginx ou Caddy:
| URL | Action |
|---|---|
/_next/static/... | Servir NEXTJS_PATH/.next/static |
/_next/... | Proxy à http://localhost:3000 |
/next/... | Servir NEXTJS_PATH/public/next RÉPERTOIRE |
Exemple de configuration pour nginx:
location /_next/static/ {
alias NEXTJS_PATH/.next/static/;
expires max;
add_header Cache-Control "public";
}
location /_next/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /next/ {
alias NEXTJS_PATH/public/next/;
expires max;
add_header Cache-Control "public";
}
Démarrer le serveur Next.js:
# Development:
$ npm run dev
# Production:
$ npm run build
$ npm run startCommencez par développer vos pages dans Next.js, puis définissez une URL Django pour chaque page Next.js. Voici un exemple de la façon dont vous pouvez faire cela:
from django_nextjs . views import nextjs_page
urlpatterns = [
path ( "/nextjs/page" , nextjs_page (), name = "nextjs_page" ),
]Même s'il n'est pas recommandé, vous devrez parfois ajouter des étapes personnalisées avant d'afficher une page suivante.js dans Django. Cependant, nous vous conseillons de déplacer cette logique vers Next.js pour nous assurer qu'elle est appliquée même pendant les redirections côté client . Si vous vous trouvez dans cette situation, vous pouvez créer une vue asynchrone pour chaque page comme démontré ci-dessous:
from django_nextjs . render import render_nextjs_page
async def jobs ( request ):
# Your custom logic
return await render_nextjs_page ( request )Vous pouvez modifier le code HTML que Next.js renvoie dans votre code Django.
Éviter le code en double pour la barre de navigation et le pied de page est un cas d'utilisation courant pour cela si vous utilisez les modèles Next.js et Django. Sans cela, vous devrez écrire et maintenir deux versions distinctes de votre Navbar et Footer (une version de modèle Django et une version Next.js). Cependant, vous pouvez simplement créer un modèle django pour votre Navbar et insérer son code au début de la balise <body> retournée de Next.js.
Pour activer cette fonctionnalité, vous devez personnaliser le document et la disposition root dans Next.js et effectuer les ajustements suivants:
id="__django_nextjs_body" comme premier attribut de <body> élément.<div id="__django_nextjs_body_begin" /> comme premier élément à l'intérieur <body> .<div id="__django_nextjs_body_end" /> comme dernier élément à l'intérieur <body> .Remarque: Actuellement, la personnalisation HTML ne fonctionne pas avec le routeur App (next.js 13+).
Lisez ce doc et personnalisez votre document Next.js:
// pages/_document.jsx (or .tsx)
...
< body id = "__django_nextjs_body" >
< div id = "__django_nextjs_body_begin" />
< Main />
< NextScript />
< div id = "__django_nextjs_body_end" />
</ body >
. . . Écrivez un modèle django qui étend django_nextjs/document_base.html :
{% extends "django_nextjs/document_base.html" %}
{% block head %}
<!-- ... the content you want to place at the beginning of "head" tag ... -->
{{ block.super }}
<!-- ... the content you want to place at the end of "head" tag ... -->
{% endblock %}
{% block body %}
... the content you want to place at the beginning of "body" tag ...
... e.g. include the navbar template ...
{{ block.super }}
... the content you want to place at the end of "body" tag ...
... e.g. include the footer template ...
{% endblock %} Passez le nom du modèle à nextjs_page ou render_nextjs_page :
from django_nextjs . render import render_nextjs_page
from django_nextjs . views import nextjs_page
async def jobs ( request ):
return await render_nextjs_page ( request , template_name = "path/to/template.html" )
urlpatterns = [
path ( "/nextjs/page" , nextjs_page ( template_name = "path/to/template.html" ), name = "nextjs_page" ),
path ( "/jobs" , jobs , name = "jobs_page" )
]public de next.js, ce fichier doit être dans le sous-répertoire public/next pour fonctionner correctement.APPEND_SLASH = False dans settings.py de votre projet Django.py. De plus, n'ajoutez pas / à la fin des chemins NextJS dans urls.pyParamètres par défaut:
NEXTJS_SETTINGS = {
"nextjs_server_url" : "http://127.0.0.1:3000" ,
"ensure_csrf_token" : True ,
}nextjs_server_url L'URL npm run start serveur npm run dev .
ensure_csrf_token Si l'utilisateur n'a pas de jeton CSRF, assurez-vous que l'on est généré et inclus dans la demande initiale au serveur suivant.js en appelant django.middleware.csrf.get_token de Django. Si django.middleware.csrf.CsrfViewMiddleware est installé, la réponse initiale inclura un en-tête Set-Cookie pour persister la valeur de jeton CSRF sur le client. Ce comportement est activé par défaut.
ensure_csrf_token ? Vous devrez peut-être émettre des demandes de publication GraphQL pour récupérer les données dans next.js getServerSideProps . S'il s'agit de la première demande de l'utilisateur, il n'y aura pas de cookie CSRF, provoquant l'échec de la demande car GraphQL utilise le post même pour la récupération des données. Cependant, tant que les fonctions getServerSideProps sont sans effet secondaire (c'est-à-dire qu'ils n'utilisent pas de méthodes HTTP dangereuses ou de mutations GraphQL), cela devrait être bien dans une perspective de sécurité. Lisez la suite ici.
pip install -e '.[dev]'pre-commit install . Mit