跳转到主要内容

Next.js + Django集成

项目描述

Django Next.js

Next.js集成到Django项目。

因此,您想在项目中同时使用Django和Next.js。有两种情况

  1. 您正在启动一个新项目,并且想使用Django作为后端,Next.js作为前端。Django只处理API请求。所有前端代码都位于Next.js中,您不需要编写任何Django模板。

    在这种情况下,您不需要这个包(尽管可以使用它)。您只需启动Django和Next.js服务器,并将您的公共Web服务器指向Next.js。

  2. 您需要同时使用Django模板和Next.js,并且这些页面应能够轻松链接。也许您有一个现有的Django项目,其中包含由Django模板渲染的页面,并且想添加一些新的Next.js页面。或者,您想将前端迁移到Next.js,但由于项目较大,您需要逐步进行。

    在这种情况下,这个包是为您准备的!

它是如何工作的?

来自StackOverflow上的评论

在同一服务器上运行2个端口。一个用于Django(面向公众)和一个用于Next.js(内部)。让Django处理所有Web请求。对于每个请求,从Django视图查询Next.js以获取HTML响应。从Django视图返回确切的HTML响应。

安装

  • 从PyPI安装最新版本。

    pip install django-nextjs
    
  • django_nextjs.apps.DjangoNextJSConfig添加到INSTALLED_APPS

  • 根据您的环境设置Next.js URL。

设置Next.js URL(开发环境)

如果在开发期间通过ASGI提供服务,请使用Django Channels并将NextJSProxyHttpConsumerNextJSProxyWebsocketConsumer添加到asgi.py,如下例所示。

注意:我们建议使用ASGI和Django Channels,因为这是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中。这可能会导致死锁。

设置Next.js URL(生产环境)

在生产中,使用Nginx或Caddy等反向代理。

URL 动作
/_next/static/... 提供NEXTJS_PATH/.next/static目录
/_next/... 代理到http://localhost:3000
/next/... 提供NEXTJS_PATH/public/next目录

Ngxin配置示例

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中开发您的页面,然后为每个Next.js页面定义一个Django URL。以下是如何操作的示例

from django_nextjs.views import nextjs_page

urlpatterns = [
    path("/nextjs/page", nextjs_page(), name="nextjs_page"),
]

尽管不建议这样做,但有时您可能需要在Django中显示Next.js页面之前添加一些自定义步骤。然而,我们建议将此逻辑移至Next.js以确保即使在客户端重定向期间也适用。如果您发现自己处于这种情况,可以像下面那样为每个页面创建一个异步视图

from django_nextjs.render import render_nextjs_page

async def jobs(request):
    # Your custom logic
    return await render_nextjs_page(request)

自定义HTML响应

您可以在Django代码中修改Next.js返回的HTML代码。

避免重复编写导航栏和页脚的代码是此功能的常见用例,如果您同时使用Next.js和Django模板。否则,您将不得不编写并维护两个版本的导航栏和页脚(Django模板版本和Next.js版本)。但是,您可以简单地创建一个Django模板用于导航栏,并在Next.js返回的<body>标签的开头插入其代码。

要启用此功能,您需要自定义Next.js中的文档和根布局,并做出以下调整

  • id="__django_nextjs_body"作为<body>元素的第一个属性。
  • <div id="__django_nextjs_body_begin" />作为<body>中的第一个元素。
  • <div id="__django_nextjs_body_end" />作为<body>中的最后一个元素。

注意:目前HTML自定义功能不与app路由(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_nextjs/document_base.html的Django模板

{% 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_pagerender_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")
]

注意

  • 如果您要将文件添加到Next.js的public目录,则该文件应在public/next子目录中才能正常工作。
  • 如果您使用Django channels,请确保所有中间件都是异步兼容的
  • 为了避免“过多重定向”错误,您可能需要在Django项目的settings.py中添加APPEND_SLASH = False。另外,请不要在urls.py中的nextjs路径末尾添加/
  • 此包不提供从Django传递数据到Next.js的解决方案。应继续使用Django Rest Framework、GraphQL或类似解决方案。
  • 此包不会运行Next.js服务器。您需要自行运行它。

设置

默认设置

    NEXTJS_SETTINGS = {
        "nextjs_server_url": "http://127.0.0.1:3000",
        "ensure_csrf_token": True,
    }

nextjs_server_url

Next.js服务器地址(由npm run devnpm run start启动)

ensure_csrf_token

如果用户没有CSRF令牌,则通过调用Django的django.middleware.csrf.get_token确保生成一个令牌并将其包含在发送到Next.js服务器的初始请求中。如果安装了django.middleware.csrf.CsrfViewMiddleware,则初始响应将包括一个Set-Cookie头,以在客户端持久化CSRF令牌值。默认情况下启用此行为。

何时需要ensure_csrf_token

您可能需要在Next.js的getServerSideProps中发出GraphQL POST请求以获取数据。如果这是用户的第一个请求,则不会有CSRF cookie,导致请求失败,因为GraphQL即使在数据获取时也使用POST。但是,只要getServerSideProps函数是副作用免费的(即,它们不使用HTTP不安全的方法或GraphQL突变),从安全角度来看应该没问题。更多信息请参阅这里

开发

  • 使用pip install -e '.[dev]'在您的虚拟环境中安装开发依赖项。
  • 使用pre-commit install安装pre-commit钩子。

参考

许可证

MIT

项目详情


下载文件

下载您平台上的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分布

django_nextjs-3.2.0.tar.gz (16.1 kB 查看哈希值)

上传时间

构建分布

django_nextjs-3.2.0-py3-none-any.whl (12.1 kB 查看哈希值)

上传时间 Python 3

支持者:

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面