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
Hello world written in Django.

Learning Django 💡 create a virtual environment create python -m venv ./venv. this virtualenv file will be excluded by .gitignore activate the virtual

Dipak giri 4 Nov 26, 2021
a little task queue for python

a lightweight alternative. huey is: a task queue (2019-04-01: version 2.0 released) written in python (2.7+, 3.4+) clean and simple API redis, sqlite,

Charles Leifer 4.3k Dec 29, 2022
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
Domain-driven e-commerce for Django

Domain-driven e-commerce for Django Oscar is an e-commerce framework for Django designed for building domain-driven sites. It is structured such that

Oscar 5.6k Jan 01, 2023
A Django app for managing robots.txt files following the robots exclusion protocol

Django Robots This is a basic Django application to manage robots.txt files following the robots exclusion protocol, complementing the Django Sitemap

Jazzband 406 Dec 26, 2022
This is raw connection between redis server and django python app

Django_Redis This repository contains the code for this blogpost. Running the Application Clone the repository git clone https://github.com/xxl4tomxu9

Tom Xu 1 Sep 15, 2022
An example of Django project with basic user functionality and account activation.

Simple Django Login and Registration An example of Django project with basic user functionality. Screenshots Log In Create an account Authorized page

Hussein Sarea 3 Oct 19, 2022
Automatically upgrade your Django projects.

django-upgrade Automatically upgrade your Django projects. Installation Use pip: python -m pip install django-upgrade Python 3.8 to 3.10 supported. Or

Adam Johnson 525 Dec 29, 2022
Website desenvolvido em Django para gerenciamento e upload de arquivos (.pdf).

Website para Gerenciamento de Arquivos Features Esta é uma aplicação full stack web construída para desenvolver habilidades com o framework Django. O

Alinne Grazielle 8 Sep 22, 2022
Django models and endpoints for working with large images -- tile serving

Django Large Image Models and endpoints for working with large images in Django -- specifically geared towards geospatial tile serving. DISCLAIMER: th

Resonant GeoData 42 Dec 17, 2022
Custom Django field for using enumerations of named constants

django-enumfield Provides an enumeration Django model field (using IntegerField) with reusable enums and transition validation. Installation Currently

5 Monkeys 195 Dec 20, 2022
Stream Framework is a Python library, which allows you to build news feed, activity streams and notification systems using Cassandra and/or Redis. The authors of Stream-Framework also provide a cloud service for feed technology:

Stream Framework Activity Streams & Newsfeeds Stream Framework is a Python library which allows you to build activity streams & newsfeeds using Cassan

Thierry Schellenbach 4.7k Jan 02, 2023
Tweak the form field rendering in templates, not in python-level form definitions. CSS classes and HTML attributes can be altered.

django-widget-tweaks Tweak the form field rendering in templates, not in python-level form definitions. Altering CSS classes and HTML attributes is su

Jazzband 1.8k Jan 02, 2023
Django Rest Framework + React application.

Django Rest Framework + React application.

2 Dec 19, 2022
Easily share data across your company via SQL queries. From Grove Collab.

SQL Explorer SQL Explorer aims to make the flow of data between people fast, simple, and confusion-free. It is a Django-based application that you can

Grove Collaborative 2.1k Dec 30, 2022
Automatic caching and invalidation for Django models through the ORM.

Cache Machine Cache Machine provides automatic caching and invalidation for Django models through the ORM. For full docs, see https://cache-machine.re

846 Nov 26, 2022
Django Girls Tutorial Workshop

Django Girls Tutorial Workshop A log of activities during the workshop. this is an H2 git remote add origin https://github.com/ahuimanu/django_girls_t

Jeffry Babb 1 Oct 27, 2021
Reusable workflow library for Django

django-viewflow Viewflow is a lightweight reusable workflow library that helps to organize people collaboration business logic in django applications.

Viewflow 2.3k Jan 08, 2023
This is a sample Django Form.

Sample FORM Installation guide Clone repository git clone https://github.com/Ritabratadas343/SampleForm.git cd to repository. Create a virtualenv by f

Ritabrata Das 1 Nov 05, 2021
Official clone of the Subversion repository.

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. All documentation is in the "docs" directo

Raymond Penners 3 May 06, 2022