Project Icon

django-nextjs

Django与Next.js的无缝集成方案

Django Next.js是一个集成解决方案,实现了Django项目与Next.js的无缝结合。该项目支持同时使用Django模板和Next.js页面,适用于需要逐步迁移或并行使用两种技术的场景。它提供了简便的配置过程、灵活的URL设置和HTML响应定制功能,有助于提升全栈开发效率。

Django Next.js

Django项目的Next.js集成。

如果你想在项目中同时使用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, 因为这对于Next.js 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

# 如果需要,在这里放置你的自定义路由
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的ASGI应用程序处理传统的HTTP和websocket请求。
        "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目录

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服务器:

# 开发:
$ npm run dev

# 生产:
$ 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):
    # 你的自定义逻辑
    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>元素的第一个属性。
  • <body>内部添加<div id="__django_nextjs_body_begin" />作为第一个元素。
  • <body>内部添加<div id="__django_nextjs_body_end" />作为最后一个元素。

注意:目前HTML自定义不适用于app router(Next.js 13+)。

阅读此文档 并自定义你的Next.js文档:

// pages/_document.jsx (或 .tsx)
...
<body id="__django_nextjs_body">
  <div id="__django_nextjs_body_begin" />
  <Main />
  <NextScript />
  <div id="__django_nextjs_body_end" />
</body>
...
// app/layout.jsx (或 .tsx)
...
<body id="__django_nextjs_body" className={inter.className}>
  <div id="__django_nextjs_body_begin" />
  {children}
  <div id="__django_nextjs_body_end" />
</body>
...
``` -->

编写一个继承自 `django_nextjs/document_base.html` 的 Django 模板:

```django
{% extends "django_nextjs/document_base.html" %}


{% block head %}
  <!-- ... 你想放在 "head" 标签开头的内容 ... -->
  {{ block.super }}
  <!-- ... 你想放在 "head" 标签结尾的内容 ... -->
{% endblock %}


{% block body %}
  ... 你想放在 "body" 标签开头的内容 ...
  ... 例如,包含导航栏模板 ...
  {{ block.super }}
  ... 你想放在 "body" 标签结尾的内容 ...
  ... 例如,包含页脚模板 ...
{% 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 服务器的 URL(通过 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 安装预提交钩子。

参考

许可

MIT

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号