Django + Next.js integration

Related tags

Djangodjango-nextjs
Overview

Django Next.js

Django + Next.js integration

From a comment on StackOverflow:

Run 2 ports on the same server. One for django (public facing) and one for Next.js (internal). Let django handle all web requests. For each request, query Next.js from django view to get HTML response. Return that exact HTML response from django view.

Installation

  • Install the latest version from PyPI.

    pip install django-nextjs
  • Add django_nextjs to INSTALLED_APPS.

  • In Development Environment:

    • If you're using django channels, add NextJSProxyHttpConsumer and NextJSProxyWebsocketConsumer to asgi.py:

      import os
      
      from django.core.asgi import get_asgi_application
      from django.urls import re_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 = [...]
      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)),
              # ...
          }
      )
    • Otherwise, add the following to the beginning of urls.py:

      path("", include("django_nextjs.urls"))
  • In Production:

    • Use a reverse proxy like nginx:

      URL Action
      /_next/static/... Serve NEXTJS_PATH/.next/static directory
      /_next/... Proxy to http://localhost:3000
      /next/... Serve NEXTJS_PATH/public/next directory

      Pass x-real-ip header when proxying /_next/:

      location /_next/ {
          proxy_set_header  x-real-ip $remote_addr;
          proxy_pass  http://127.0.0.1:3000;
      }
      

Usage

Start Next.js server:

# Development:
$ npm run dev

# Production:
$ npm run build
$ npm run start

Develop your pages in Next.js. Write a django URL and view for each page like this:

# If you're using django channels
from django.http import HttpResponse
from django_nextjs.render import render_nextjs_page_async

async def jobs(request):
    return await render_nextjs_page_async(request)
# If you're not using django channels
from django.http import HttpResponse
from django_nextjs.render import render_nextjs_page_sync

def jobs(request):
    return render_nextjs_page_sync(request)

Customizing Document

If you want to customize the HTML document (e.g. add header or footer), read this section.

You need to customize Next's document:

  • Add id="__django_nextjs_body" as the first attribute of <body> element.
  • Add <div id="__django_nextjs_body_begin" /> as the first element inside <body>.
  • Add <div id="__django_nextjs_body_end" /> as the last element inside <body>.
import Document, { Html, Head, Main, NextScript } from "next/document";

// https://nextjs.org/docs/advanced-features/custom-document
class MyDocument extends Document {
  render() {
    return (
      <Html>
        <Head />
        <body id="__django_nextjs_body" dir="rtl">
          <div id="__django_nextjs_body_begin" />
          <Main />
          <NextScript />
          <div id="__django_nextjs_body_end" />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

Write a django template that extends django_nextjs/document_base.html:

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


{% block head %}
  ... the content you want to add to the beginning of <head> tag ...
  {{ block.super }}
  ... the content you want to add to the end of <head> tag ...
{% endblock %}


{% block body %}
  ... the content you want to add to the beginning of <body> tag ...
  {{ block.super }}
  ... the content you want to add to the end of <body> tag ...
{% endblock %}

Pass the template name to render_nextjs_page_async or render_nextjs_page_sync:

# If you're using django channels
async def jobs(request):
    return await render_nextjs_page_async(request, "path/to/template.html")
# If you're not using django channels
def jobs(request):
    return render_nextjs_page_sync(request, "path/to/template.html")

Notes

  • If you want to add a file to public directory of Next.js, that file should be in public/next subdirectory to work correctly.
  • If you're using django channels, make sure all your middlewares are async-capable.

Settings

Default settings:

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

nextjs_server_url

The URL of Next.js server (started by npm run dev or npm run start)

Development

  • Install development dependencies in your virtualenv with pip install -e '.[dev]'
  • Install pre-commit hooks using pre-commit install.

References

Comments
  • _next/webpack-hmr' failed: / Too many redirects

    _next/webpack-hmr' failed: / Too many redirects

    Hello,

    i've try to install the package like described in the readme.

    Environment:

    • Next.js v12.2.4
    • Django 4.0.6

    Everything was installed successfully but i have several errors:

    First of all on index js i get the error: WebSocket connection to 'ws://127.0.0.1:8000/_next/webpack-hmr' failed: Bildschirmfoto 2022-08-09 um 19 40 11

    But i can see the nextjs index.

    Then i want to try to change the route to /test

    I described a view and parsed it to the url. If i call the url i got the error: too many redirects and the page wouldn't load:

    Bildschirmfoto 2022-08-09 um 19 43 54 Bildschirmfoto 2022-08-09 um 19 43 49

    Here my Settings.py:

    from pathlib import Path
    
    BASE_DIR = Path(__file__).resolve().parent.parent
    
    SECRET_KEY = 'django-insecure-%2spqobsw&i$k(n(%(siwd#fxzh^h%wqk5nc3nx0_$upu8r5!q'
    
    DEBUG = True
    
    ALLOWED_HOSTS = []
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        "django_nextjs",
    ]
    
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
    ROOT_URLCONF = 'empire_next.urls'
    
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    
    WSGI_APPLICATION = 'empire_next.wsgi.application'
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': BASE_DIR / 'db.sqlite3',
        }
    }
    
    
    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]
    
    
    LANGUAGE_CODE = 'en-us'
    
    TIME_ZONE = 'UTC'
    
    USE_I18N = True
    
    USE_TZ = True
    
    
    STATIC_URL = 'static/'
    
    
    
    DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
    

    views.py

    from django.shortcuts import render
    
    # Create your views here.
    
    from django_nextjs.render import render_nextjs_page_sync
    
    
    def index(request):
        return render_nextjs_page_sync(request)
    
    
    def test(request):
        return render_nextjs_page_sync(request)
    

    urls.py

    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path("", include("backend.urls")),
        path("", include("django_nextjs.urls")),
    ]
    

    backend.urly.py:

    from django.urls import path
    from .views import index
    urlpatterns = [
        path("", index, name="index"),
        path("test/", index, name="test"),
    ]
    

    any solution for this?

    opened by Amplitude88 9
  • for next.js v12 thru Django channels, 'admin/' doesn't work

    for next.js v12 thru Django channels, 'admin/' doesn't work

    after changing to channels with asgi.py, 'admin' listed in urls.py can not accessed correctly. any guidance about how to handle middleware like this? Thanks,

    my urls.py is:

    from django.contrib import admin
    from django.urls import include, path, re_path
    from django.views.generic.base import RedirectView
    # from .views import jobs
    
    # favicon_view = RedirectView.as_view(url='static/vercel.svg', permanent=True)
    
    urlpatterns = [
        # path('', jobs),
        path('admin/', admin.site.urls),
        re_path(r'^vercel\.svg$', RedirectView.as_view(url='static/vercel.svg')),
        path('favicon.ico', RedirectView.as_view(url='static/favicon.ico')),  
    ]
    

    all these 3 paths are not working if channels and django-nextjs enabled in INSTALLED_APPS in settings.py.

    opened by crossz 6
  • Issue when running nextjs

    Issue when running nextjs

    hey my nextjs version is:

    @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ @next/[email protected]
    ├─ [email protected]
    │  ├─ @next/[email protected]
    │  ├─ resolve@^2.0.0-next.3
    │  ├─ [email protected]
    ├─ [email protected]
    │  ├─ @next/[email protected]
    │  ├─ @next/[email protected]
    │  ├─ @next/[email protected]
    │  ├─ @next/[email protected]
    │  ├─ @next/[email protected]
    │  ├─ @next/[email protected]
    │  ├─ @next/[email protected]
    │  ├─ @next/[email protected]
    │  ├─ @next/[email protected]
    │  ├─ @next/[email protected]
    │  ├─ @next/[email protected]
    │  ├─ @next/s[email protected]
    │  ├─ @next/[email protected]
    

    I am getting 'WebSocket connection to 'ws://localhost:8000/_next/webpack-hmr' failed: ' screenshot attached Screenshot at May 26 22-07-27

    opened by aashishg 6
  • Issues when running the Django server in production mode

    Issues when running the Django server in production mode

    Hi,

    If the Django server is set to run with debug=False, then all the requests will pass through the render_nextjs_page_sync, according to this statement in urls.py:

    if settings.DEBUG:
        # only in dev environment
        urlpatterns.append(re_path(r"^(?:_next|__nextjs|next).*$", NextJSProxyView.as_view()))
    

    The problem is that all the .js bundles requests will have their content-type property set to text/html, as this is happening for each request that passes through this view:

    from django_nextjs.render import render_nextjs_page_sync
    
    def index(request):
        return render_nextjs_page_sync(request)
    

    Should the content-type be manually computed and then specified as an argument to the render_nextjs_page_sync method? I don't see other way around it.

    Thank you!

    opened by ISilviu 2
  • Add redirect support

    Add redirect support

    Currently, redirects received from the NextJS server are not supported. More specifically, I'm referring to this kind of redirects:

    image

    I have roughly added support for 308 codes, yet the implementation is not tested nor does it feel complete. Could you please guide me on how to complete this implementation?

    opened by ISilviu 2
  • Pass allow_redirects parameter to render function

    Pass allow_redirects parameter to render function

    Hello, I am a Korean django developer.

    I work for a company called Buildblock and I want to change the frontend technology stack from django template to nextjs. However, django couldn't recognize the static file built in nextjs and ended up using django-nextjs.

    However, redirects are required for translation on our website, but django-nextjs redirects were rejected because allow_redirects was False. So this error occurred.

    Therefore, it is suggested to add allow_redirects as a parameter to the render_nextjs_page_sync function. We confirmed that this change would give us the desired behavior.

    I look forward to a good answer. thank you

    opened by SeokEunJu 1
  • for next.js v12 vercel.svg can not loaded

    for next.js v12 vercel.svg can not loaded

    After changing to Django channels and asgi.py in order to make websocket work, I tried all static files deployment configuration for Django 4, nothing works for correct loading vercel.svg. Please provide some guidance about this.

    opened by crossz 1
  • Cannot visit another endpoint

    Cannot visit another endpoint

    I followed the steps from this tutorial. I added the created a new app called frontend and added the following codes:

    # myproject/urls.py
    from django.urls import include, path
    urlpatterns = [
        # ...
        path("", include("frontend.urls")),
        path("", include("django_nextjs.urls")),
    ]
    
    # frontend/views.py
    from django_nextjs.render import render_nextjs_page_sync
    def index(request):
        return render_nextjs_page_sync(request)
    
    # frontend/urls.py
    from django.urls import path
    from .views import index
    urlpatterns = [
        path("", index, name="index"),
    ]
    

    I can now see the homepage (situated at "localhost:8000/" route) But I can't visit any other routes like "http://localhost:8000/create" which I can visit from my nextjs server "http://localhost:3000/create".

    I tried adding a new route in frontend.urls.py like this

    from django.urls import path
    from .views import index
    
    urlpatterns = [
        path("", index, name="index"),
        path("create/", index, name="index"),
    ]
    

    but I kept getting too many redirects. Can someone show me the correct way to do this or is it even necessary to add endpoints manually?

    opened by sugamkarki 1
  • Use ** syntax

    Use ** syntax

    I'm unable to use the library on a Python 3.8.5 environment, it complaints about the following issue:

    unsupported operand type(s) for |: 'dict' and 'dict'
    

    Couldn't the library just use the ** syntax, which is supported starting from Python 3.5?

    opened by ISilviu 1
  • Want to pass allow_redirects parameter to render function

    Want to pass allow_redirects parameter to render function

    While using django-nextjs, there is a situation where need to set allow_redirects to True, so I suggest adding the allow_redirects field as a parameter to functions such as render_nextjs_page_sync.

    Please check here for details.

    thank you.

    opened by SeokEunJu 0
  • Incorrect Type Annotations

    Incorrect Type Annotations

    Some type annotations are incorrect, e.g. the return type of render_nextjs_page_sync and render_nextjs_page_async.

    https://github.com/QueraTeam/django-nextjs/blob/d29b04e8064afbff2496430e7b3bbda81a78ee16/django_nextjs/render.py#L62

    https://github.com/QueraTeam/django-nextjs/blob/d29b04e8064afbff2496430e7b3bbda81a78ee16/django_nextjs/render.py#L103

    https://github.com/QueraTeam/django-nextjs/blob/d29b04e8064afbff2496430e7b3bbda81a78ee16/django_nextjs/render.py#L112

    https://github.com/QueraTeam/django-nextjs/blob/d29b04e8064afbff2496430e7b3bbda81a78ee16/django_nextjs/render.py#L154

    opened by mjnaderi 0
Releases(v2.2.1)
Owner
Quera
Practice Programming, Compete, Find Tech Jobs!
Quera
Use heroicons in your Django and Jinja templates.

heroicons Use heroicons in your Django and Jinja templates. Requirements Python 3.6 to 3.9 supported. Django 2.2 to 3.2 supported. Are your tests slow

Adam Johnson 52 Dec 14, 2022
Django web apps for managing schedules.

skdue Description Skdue is a web application that makes your life easier by helping you manage your schedule. With the ability which allows you to cre

Patkamon_Awai 1 Jun 30, 2022
A blog app powered by python-django

Django_BlogApp This is a blog app powered by python-django Features Add and delete blog post View someone else blog Can add comment to that blog And o

Manish Jalui 1 Sep 12, 2022
PEP-484 type hints bindings for the Django web framework

mypy-django Type stubs to use the mypy static type-checker with your Django projects This project includes the PEP-484 compatible "type stubs" for Dja

Machinalis 223 Jun 17, 2022
APIs for a Chat app. Written with Django Rest framework and Django channels.

ChatAPI APIs for a Chat app. Written with Django Rest framework and Django channels. The documentation for the http end points can be found here This

Victor Aderibigbe 18 Sep 09, 2022
This is a simple Todo web application built Django (back-end) and React JS (front-end)

Django REST Todo app This is a simple Todo web application built with Django (back-end) and React JS (front-end). The project enables you to systemati

Maxim Mukhin 5 May 06, 2022
This is django-import-export module that exports data into many formats

django-import-export This is django-import-export module which exports data into many formats, you can implement this in your admin panel. - Dehydrat

Shivam Rohilla 3 Jun 03, 2021
Source code for Django for Beginners 3.2

The official source code for https://djangoforbeginners.com/. Available as an ebook or in Paperback. If you have the 3.1 version, please refer to this

William Vincent 10 Jan 03, 2023
A simple demonstration of how a django-based website can be set up for local development with microk8s

Django with MicroK8s Start Building Your Project This project provides a Django web app running as a single node Kubernetes cluster in microk8s. It is

Noah Jacobson 19 Oct 22, 2022
A simple plugin to attach a debugger in Django on runserver command.

django-debugger A simple plugin to attach a debugger in Django during runserver Installation pip install django-debugger Usage Prepend django_debugger

Sajal Shrestha 11 Nov 15, 2021
Django/Jinja template indenter

DjHTML A pure-Python Django/Jinja template indenter without dependencies. DjHTML is a fully automatic template indenter that works with mixed HTML/CSS

Return to the Source 378 Jan 01, 2023
Store model history and view/revert changes from admin site.

django-simple-history django-simple-history stores Django model state on every create/update/delete. This app supports the following combinations of D

Jazzband 1.8k Jan 06, 2023
Built from scratch to replicate some of the Django admin functionality and add some more, to serve as an introspective interface for Django and Mongo.

django-mongonaut Info: An introspective interface for Django and MongoDB. Version: 0.2.21 Maintainer: Jazzband (jazzband.co) This Project is Being Mov

Jazzband 238 Dec 26, 2022
Simple API written in Python using FastAPI to store and retrieve Books and Authors.

Simple API made with Python FastAPI WIP: Deploy in AWS with Terraform Simple API written in Python using FastAPI to store and retrieve Books and Autho

Caio Delgado 9 Oct 26, 2022
Django Rest Framework + React application.

Django Rest Framework + React application.

2 Dec 19, 2022
Comprehensive Markdown plugin built for Django

Django MarkdownX Django MarkdownX is a comprehensive Markdown plugin built for Django, the renowned high-level Python web framework, with flexibility,

neutronX 738 Dec 21, 2022
A Django backed for PostgreSQL using Psycopg 3

A Django backend for PostgreSQL using Psycopg 2 The backend passes the entire Django test suite, but it needs a few modifications to Django and to i

Daniele Varrazzo 42 Dec 16, 2022
Auto-detecting the n+1 queries problem in Python

nplusone nplusone is a library for detecting the n+1 queries problem in Python ORMs, including SQLAlchemy, Peewee, and the Django ORM. The Problem Man

Joshua Carp 837 Dec 29, 2022
Twitter Bootstrap for Django Form

Django bootstrap form Twitter Bootstrap for Django Form. A simple Django template tag to work with Bootstrap Installation Install django-bootstrap-for

tzangms 557 Oct 19, 2022
Median and percentile for Django and MongoEngine

Tailslide Median and percentile for Django and MongoEngine Supports: PostgreSQL SQLite MariaDB MySQL (with an extension) SQL Server MongoDB 🔥 Uses na

Andrew Kane 4 Jan 15, 2022