Next.js集成Django項目。
因此,您想在項目中同時使用Django和Next.js。有兩種情況:
您正在啟動一個新項目,並且想將Django用作後端,而Next.js作為前端。 Django僅服務於API請求。所有前端代碼都生活在Next.js中,您不會編寫任何Django模板。
在這種情況下,您不需要此軟件包(儘管可以使用)。您只需啟動Django和Next.js服務器,然後將您的公共網絡服務器指向Next.js。
您同時需要django模板和next.js,這些頁面應輕鬆鏈接。也許您有一個現有的Django項目,該項目的頁面由Django模板呈現,並希望在Next.js中進行一些新頁面。或者,您想將前端遷移到Next.js,但是由於該項目很大,因此您需要逐步進行。
在這種情況下,此軟件包適合您!
從關於Stackoverflow的評論:
在同一服務器上運行2個端口。一個用於django(公共面),另一個用於next.js(內部)。讓Django處理所有Web請求。對於每個請求,請查詢django視圖的Next.js以獲取HTML響應。從Django View返回確切的HTML響應。
從PYPI安裝最新版本。
pip install django-nextjs添加django_nextjs.apps.DjangoNextJSConfig到INSTALLED_APPS 。
根據您的環境設置Next.js URL。
如果您在開發過程中在ASGI下為您的網站提供服務,請使用Django頻道,並添加NextJSProxyHttpConsumer , NextJSProxyWebsocketConsumer asgi.py如下示例。
注意:我們建議使用ASGI和Django通道,因為快速刷新(熱模塊更換)需要在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 )),
# ...
}
)否則(如果在開發過程中為WSGI服務),請將以下內容添加到urls.py的開頭:
path ( "" , include ( "django_nextjs.urls" ))警告:如果您要在ASGI下服務,請不要將其添加到您的urls.py中。這可能會造成僵局。
在生產中,使用諸如Nginx或Caddy之類的反向代理:
| URL | 行動 |
|---|---|
/_next/static/... | 服務NEXTJS_PATH/.next/static Directory |
/_next/... | 代理到http://localhost:3000 |
/next/... | 服務NEXTJS_PATH/public/next目錄 |
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";
}
啟動Next.js服務器:
# Development:
$ npm run dev
# Production:
$ npm run build
$ npm run start首先在Next.js中開發您的頁面,然後為每個下一個頁面定義一個Django URL。這是一個可以做到這一點的示例:
from django_nextjs . views import nextjs_page
urlpatterns = [
path ( "/nextjs/page" , nextjs_page (), name = "nextjs_page" ),
]即使不建議這樣做,有時您可能需要在Django中顯示下一個JS頁面之前添加一些自定義步驟。但是,我們建議將此邏輯移至Next.js,以確保即使在客戶端重定向期間也將其應用。如果您發現自己處於這種情況,則可以為每個頁面創建一個異步視圖,如下所示:
from django_nextjs . render import render_nextjs_page
async def jobs ( request ):
# Your custom logic
return await render_nextjs_page ( request )您可以修改Next.js在Django代碼中返回的HTML代碼。
如果您同時使用Next.js和Django模板,則避免使用Navbar和頁腳的重複代碼是常見的用例。沒有它,您將不得不編寫和維護兩個單獨的納維欄和頁腳版本(django模板版本和next.js版本)。但是,您只需為您的Navbar創建一個Django模板,然後在<body>標籤的開頭插入其代碼,從Next.js返回。
要啟用此功能,您需要在Next.js中自定義文檔和根佈局,然後進行以下調整:
id="__django_nextjs_body"作為<body>元素的第一個屬性。<div id="__django_nextjs_body_begin" />作為<body>內部的第一個元素。<div id="__django_nextjs_body_end" />作為<body>內部的最後一個元素。注意:當前HTML自定義不使用App Router(Next.js 13+)。
閱讀此文檔並自定義您的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 >
. . .編寫一個django模板,該模板擴展了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 %}將模板名稱傳遞到nextjs_page或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目錄中,則該文件應在public/next子目錄中正確工作。settings.py中添加APPEND_SLASH = False 。另外,請勿在urls.py中的NextJS路徑的末尾添加/ 。默認設置:
NEXTJS_SETTINGS = {
"nextjs_server_url" : "http://127.0.0.1:3000" ,
"ensure_csrf_token" : True ,
}nextjs_server_url Next.js服務器的URL(由npm run dev或npm run start )
ensure_csrf_token如果用戶沒有CSRF令牌,請通過調用Django的django.middleware.csrf.get_token來確保生成並包含在Next.js服務器的初始請求中。 If django.middleware.csrf.CsrfViewMiddleware is installed, the initial response will include a Set-Cookie header to persist the CSRF token value on the client.默認情況下啟用了此行為。
ensure_csrf_token時?您可能需要在Next.js getServerSideProps中發布GraphQl Post請求以獲取數據。如果這是用戶的第一個請求,則不會有CSRF cookie,從而導致請求失敗,因為GraphQl甚至用於數據獲取的帖子。但是,只要getServerSideProps函數是無副作用的(即它們不使用HTTP不安全方法或GraphQL突變),從安全角度來看,這應該很好。在這裡閱讀更多。
pip install -e '.[dev]'pre-commit install加壓鉤。 麻省理工學院