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
Duckiter will Automatically dockerize your Django projects.

Duckiter Duckiter will Automatically dockerize your Django projects. Requirements : - python version : python version 3.6 or upper version - OS :

soroush safari 23 Sep 16, 2021
A real-time photo feed using Django and Pusher

BUILD A PHOTO FEED USING DJANGO Here, we will learn about building a photo feed using Django. This is similar to instagram, but a stripped off version

samuel ogundipe 4 Jan 01, 2020
The uncompromising Python code formatter

The Uncompromising Code Formatter “Any color you like.” Black is the uncompromising Python code formatter. By using it, you agree to cede control over

Python Software Foundation 30.7k Jan 03, 2023
PEP-484 stubs for Django

pep484 stubs for Django This package contains type stubs and a custom mypy plugin to provide more precise static types and type inference for Django f

TypedDjango 1.1k Dec 30, 2022
A simple porfolio with Django, Bootstrap and Sqlite3

Django Portofolio Example this is a basic portfolio in dark mode Installation git clone https://github.com/FaztWeb/django-portfolio-simple.git cd djan

Fazt Web 16 Sep 26, 2022
Django Pickled Model

Django Pickled Model Django pickled model provides you a model with dynamic data types. a field can store any value in any type. You can store Integer

Amir 3 Sep 14, 2022
scaffold django rest apis like a champion 🚀

dr_scaffold Scaffold django rest apis like a champion ⚡ . said no one before Overview This library will help you to scaffold full Restful API Resource

Abdenasser Elidrissi 133 Jan 05, 2023
Use Database URLs in your Django Application.

DJ-Database-URL This simple Django utility allows you to utilize the 12factor inspired DATABASE_URL environment variable to configure your Django appl

Jacob Kaplan-Moss 1.3k Dec 30, 2022
Utility for working with recurring dates in Django.

django-recurrence django-recurrence is a utility for working with recurring dates in Django. Documentation is available at https://django-recurrence.r

408 Jan 06, 2023
Актуальный сборник шаблонов для создания проектов и приложений на Django

О чем этот проект Этот репозиторий с шаблонами для быстрого создания Django проекта. В шаблоне проекта настроены следующий технологий: Django gunicorn

Denis Kustov 16 Oct 20, 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
Learn Python and the Django Framework by building a e-commerce website

The Django-Ecommerce is an open-source project initiative and tutorial series built with Python and the Django Framework.

Very Academy 275 Jan 08, 2023
Template for Django Project Using Docker

You want a Django project who use Docker and Docker-compose for Development and for Production ? It's for you !

1 Dec 17, 2021
Dockerizing Django with Postgres, Gunicorn, Nginx and Certbot. A fully Django starter project.

Dockerizing Django with Postgres, Gunicorn, Nginx and Certbot 🚀 Features A Django stater project with fully basic requirements for a production-ready

8 Jun 27, 2022
Django API creation with signed requests utilizing forms for validation.

django-formapi Create JSON API:s with HMAC authentication and Django form-validation. Version compatibility See Travis-CI page for actual test results

5 Monkeys 34 Apr 04, 2022
Bringing together django, django rest framework, and htmx

This is Just an Idea There is no code, this README just represents an idea for a minimal library that, as of now, does not exist. django-htmx-rest A l

Jack DeVries 5 Nov 24, 2022
Auth module for Django and GarpixCMS

Garpix Auth Auth module for Django/DRF projects. Part of GarpixCMS. Used packages: django rest framework social-auth-app-django django-rest-framework-

GARPIX CMS 18 Mar 14, 2022
Django REST Client API

Django REST Client API Client data provider API.

Ulysses Monteiro 1 Nov 08, 2021
This repository contains django library management system project.

Library Management System Django ** INSTALLATION** First of all install python on your system. Then run pip install -r requirements.txt to required se

whoisdinanath 1 Dec 26, 2022
demo project for django channels tutorial

django_channels_chat_official_tutorial demo project for django channels tutorial code from tutorial page: https://channels.readthedocs.io/en/stable/tu

lightsong 1 Oct 22, 2021