• Stars
    star
    344
  • Rank 123,066 (Top 3 %)
  • Language
    Python
  • License
    MIT License
  • Created almost 3 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Next.js integration for Django projects

Django Next.js

Next.js integration for Django projects.

So you want to use both Django and Next.js in your project. There are two scenarios:

  1. You are starting a new project and you want to use Django as back-end and Next.js as front-end. Django only serves API requests. All front-end code lives in Next.js and you don't write any Django template.

    In this scenario you don't need this package (although you can use it). You simply start both Django and Next.js servers and point your public webserver to Next.js.

  2. You need both Django templates and Next.js at the same time and those pages should easily link to each other. Maybe you have an existing Django project which has pages rendered by Django template and want some new pages in Next.js. Or you want to migrate your front-end to Next.js but since the project is large, you need to do it gradually.

    In this scenario, this package is for you!

How does it work?

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.apps.DjangoNextJSConfig to INSTALLED_APPS.

  • Set up Next.js URLs depending on your environment.

Setup Next.js URLs (Development Environment)

If you're serving your site under ASGI during development, use Django Channels and add NextJSProxyHttpConsumer, NextJSProxyWebsocketConsumer to asgi.py like the following example.

Note: We recommend using ASGI and Django Channels, because it is required for fast refresh (hot module replacement) to work properly in Nextjs 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

# put your custom routes here if you need
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's ASGI application to handle traditional HTTP and websocket requests.
        "http": URLRouter(http_routes),
        "websocket": AuthMiddlewareStack(URLRouter(websocket_routers)),
        # ...
    }
)

Otherwise (if serving under WSGI during development), add the following to the beginning of urls.py:

path("", include("django_nextjs.urls"))

Warning: If you are serving under ASGI, do NOT add this to your urls.py. It may cause deadlocks.

Setup Next.js URLs (Production Environment)

In production, use a reverse proxy like Nginx or Caddy:

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/. Example config for Nginx:

location /_next/static/ {
    alias NEXTJS_PATH/.next/static/;
    expires max;
    add_header Cache-Control "public";
}
location /_next/ {
    proxy_set_header  x-real-ip $remote_addr;
    proxy_pass  http://127.0.0.1:3000;
}
location /next/ {
    alias NEXTJS_PATH/public/next/;
    expires max;
    add_header Cache-Control "public";
}

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 an async view for each page like this:

from django.http import HttpResponse
from django_nextjs.render import render_nextjs_page

async def jobs(request):
    return await render_nextjs_page(request)

Customizing the HTML Response

You can modify the HTML code that Next.js returns in your Django code.

Avoiding duplicate code for the navbar and footer is a common use case for this if you are using both Next.js and Django templates. Without it, you would have to write and maintain two separate versions of your navbar and footer (a Django template version and a Next.js version). However, you can simply create a Django template for your navbar and insert its code at the beginning of <body> tag returned from Next.js.

To enable this feature, you need to customize the document and root layout in Next.js and make the following adjustments:

  • 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>.

NOTE: Currently HTML customization is not working with app router (Next.js 13+).

Read this doc and customize your Next.js document:

// pages/_document.jsx (or .tsx)
...
<body id="__django_nextjs_body">
  <div id="__django_nextjs_body_begin" />
  <Main />
  <NextScript />
  <div id="__django_nextjs_body_end" />
</body>
...

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

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


{% block head %}
  <!-- ... the content you want to place at the beginning of "head" tag ... -->
  {{ block.super }}
  <!-- ... the content you want to place at the end of "head" tag ... -->
{% endblock %}


{% block body %}
  ... the content you want to place at the beginning of "body" tag ...
  ... e.g. include the navbar template ...
  {{ block.super }}
  ... the content you want to place at the end of "body" tag ...
  ... e.g. include the footer template ...
{% endblock %}

Pass the template name to render_nextjs_page:

async def jobs(request):
    return await render_nextjs_page(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.
  • To avoid "Too many redirects" error, you may need to add APPEND_SLASH = False in your Django project's settings.py. Also, do not add / at the end of nextjs paths in urls.py.
  • This package does not provide a solution for passing data from Django to Next.js. The Django Rest Framework, GraphQL, or similar solutions should still be used.
  • The Next.js server will not be run by this package. You will need to run it yourself.

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

License

MIT

More Repositories

1

django-qsessions

Extended session backends for Django (Sessions store IP, User Agent, and foreign key to User)
Python
151
star
2

mattermost-rtl

Adds RTL support to Mattermost
Go
67
star
3

talks

Topics Presented in Our L&D Sessions
CSS
64
star
4

data-contests

Solutions of Quera Data Contests
Jupyter Notebook
50
star
5

git-ninjas

This repo is about our Practical Git course, and contains a list of users that successfully finished the course.
48
star
6

qbuild

A build system for Quera technology challenges
Perl
40
star
7

django-pwned

A collection of django password validators
Python
24
star
8

jquery-duration-picker

A simple library for picking time durations in javascript (uses jQuery and Semantic UI)
HTML
22
star
9

metabase

Docker Compose for Metabase with PostgreSQL as Application Database
19
star
10

mattermost-chat-ui

Customizes UI for better readability
Go
18
star
11

django-visit-count

Count visits using cache for Django models.
Python
15
star
12

quera-core-ui

Quera's component library based on Chakra-UI
TypeScript
12
star
13

dataanalysis_bootcamp_crawler

Web scraper implementations for a variety of websites.
HTML
9
star
14

ansible-github

Ansible module to download and install assets from Github releases page.
Python
9
star
15

mattermost-vazirmatn

Change Mattermost font to Vazirmatn
Go
7
star
16

qcalc

Python
5
star
17

qaes

An AES Cipher Encryption/Decryption Package
Python
5
star
18

recorder

Record screen easily
Python
5
star
19

docker-ssh

Docker images for setting up an SSH tunnel or sync files between two containers on different servers.
Shell
5
star
20

sql-judge-utils

Python
4
star
21

college-ml

3
star
22

dataanalysis_bootcamp_ML_sessions

Jupyter Notebook
3
star
23

qprogress

Quera Progress Bar - A decoupled progress bar to show the progress of your loops!
Python
3
star
24

sysbench

Shell
3
star
25

qinux

Qinux
Python
2
star
26

test-repository

1
star
27

qbuild-jupyter

Python
1
star
28

django-college-frontend

JavaScript
1
star
29

git-aliases

Python
1
star