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
Python CSS/Javascript minifier

Squeezeit - Python CSS and Javascript minifier Copyright (C) 2011 Sam Rudge This program is free software: you can redistribute it and/or modify it un

Smudge 152 Apr 03, 2022
Use minify-html, the extremely fast HTML + JS + CSS minifier, with Django.

django-minify-html Use minify-html, the extremely fast HTML + JS + CSS minifier, with Django. Requirements Python 3.8 to 3.10 supported. Django 2.2 to

Adam Johnson 60 Dec 28, 2022
🌟 A social media made with Django and Python and Bulma. 🎉

Vitary A simple social media made with Django Installation 🛠️ Get the source code 💻 git clone https://github.com/foxy4096/Vitary.git Go the the dir

Aditya Priyadarshi 15 Aug 30, 2022
A simple polling app made in Django and Bootstrap

DjangoPolls A Simple Polling app made with Django Instructions Make sure you have Python installed Step 1. Open a terminal Step 2. Paste the given cod

Aditya Priyadarshi 1 Nov 10, 2021
A Minimalistic Modern Django Boilerplate

A Minimalistic Modern Django Boilerplate This boilerplate is mainly for educational purposes. It is meant to be cloned as a starter code for future tu

Jonathan Adly 21 Nov 02, 2022
Tools to easily create permissioned CRUD endpoints in graphene-django.

graphene-django-plus Tools to easily create permissioned CRUD endpoints in graphene-django. Install pip install graphene-django-plus To make use of ev

Zerosoft 74 Aug 09, 2022
It takes time to start a Django Project and make it almost production-ready.

It takes time to start a Django Project and make it almost production-ready. A developer needs to spend a lot of time installing required libraries, setup a database, setup cache as well as hiding se

Khan Asfi Reza 1 Jan 01, 2022
I managed to attach the Django Framework to my Telegram Bot and set a webhook

I managed to attach the Django Framework to my Telegram Bot and set a webhook. I've been developing it from 10th of November 2021 and I want to have a basic working prototype.

Valentyn Vovchak 2 Sep 08, 2022
Full control of form rendering in the templates.

django-floppyforms Full control of form rendering in the templates. Authors: Gregor Müllegger and many many contributors Original creator: Bruno Renié

Jazzband 811 Dec 01, 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
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
A handy tool for generating Django-based backend projects without coding. On the other hand, it is a code generator of the Django framework.

Django Sage Painless The django-sage-painless is a valuable package based on Django Web Framework & Django Rest Framework for high-level and rapid web

sageteam 51 Sep 15, 2022
Improved Django model inheritance with automatic downcasting

Polymorphic Models for Django Django-polymorphic simplifies using inherited models in Django projects. When a query is made at the base model, the inh

1.4k Jan 03, 2023
An orgizational tool to keep track of tasks/projects and the time spent on them.

Django-Task-Manager Task Tracker using Python Django About The Project This project is an orgizational tool to keep track of tasks/projects and the ti

Nick Newton 1 Dec 21, 2021
This a Django TODO app project and practiced how to deploy and publish the project to Heroku

ToDo App Demo | Project Table of Contents Overview Built With Features How to use Acknowledgements Contact Overview Built With HTML CSS JS Django How

Cetin OGUT 1 Nov 19, 2021
webfest Django project @innovaccer

inno-doctor webfest Django project @innovaccer setup guide create new directory for project clone the repo with url into the directory make sure pytho

Rohit sahu 6 Oct 28, 2022
A simple app that provides django integration for RQ (Redis Queue)

Django-RQ Django integration with RQ, a Redis based Python queuing library. Django-RQ is a simple app that allows you to configure your queues in djan

RQ 1.6k Jan 06, 2023
A Django app for working with BTCPayServer

btcpay-django A Django app for working with BTCPayServer Installation pip install btcpay-django Developers Release To cut a release, run bumpversion,

Crawford 3 Nov 20, 2022
A prettier way to see Django requests while developing

A prettier way to see Django requests while developing

Adam Hill 35 Dec 02, 2022
Simple application TodoList django with ReactJS

Django & React Django We basically follow the Django REST framework quickstart guide here. Create backend folder with a virtual Python environment: mk

Flavien HUGS 2 Aug 07, 2022