In this article, we’ll create an API using Django REST Framework and a React project (frontend) which will consume the API. The idea is very simple, React will fetch some book names from the backend (Django) and render them.

Reactjs is a nice framework for frontend and Django REST framework (DRF) is another great framework for API development. I wonder how to serve React and Django projects in the same server and same port! Finally, I’ve reached a solution and today I’ll discuss it.

Backend (Django) project

I’m using Django 2 for this project. At first, create a Django project named book.

Install django-rest-framework using pip install django-rest-framework and add rest_framework to INSTALLED_APPS list in settings.py .

Create two apps named api and core using python manage.py startapp apiand python manage.py startapp core , then add the app names to INSTALLED_APPS list in settings.py .

This is our INSTALLED_APPS list in settings.py :

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    "rest_framework",
    
    "api",
    "core",
]

Edit /api/views.py and add the following codes :

from rest_framework.response import Response
from rest_framework import status
from rest_framework.decorators import api_view


# This will return a list of books
@api_view(["GET"])
def book(request):
    books = ["Pro Python", "Fluent Python", "Speaking javascript", "The Go programming language"]
return Response(status=status.HTTP_200_OK, data={"data": books})

Configure the url in book/urls.py (url configuration can be done in more elegant approach but I’m skipping it for brevity) :

from django.urls import path

from api.views import book
from core.views import index

urlpatterns = [
    path("book/", book, name="book"),
]

Start the server using python manage.py runserver , (it will run the server at default port 8000).

Test our API

Postman is a great tool for testing APIs. Open Postman and navigate to “http://127.0.0.1:8000/book/” :

Our API is working fine! Now we’ll develop the frontend using React.

Frontend (React) Project

We’ll use create-react-app package to create React project. At first, install “create-react-app” package using npm install create-react-app .

Now create the react app named “book-frontend” create-react-app book-frontend inside the project directory (book).

Change the current directory to “book-frontend” and run npm start .

It will run our frontend server at default port 3000.

Navigate to localhost:3000 in your favorite browser (I’m using google chrome) :

We’ll use two more packages in the frontend. Let’s install them first:

axios : npm install axios

react-router-dom : npm install react-router-dom

Create a folder named Component inside src folder, then inside Component folder create a folder named Book. Inside book create a javascript file name index.js (That means: /src/Component/Book/index.js).

Put the following code into index.js (this code will fetch data from backend and render them to frontend).

Our index.js :

import React, { Component } from "react";

import axios from "axios";

export default class Book extends Component {
  constructor(props) {
    super(props);
    this.state = {
    books:[],
    };
    this.loadBooks = this.loadBooks.bind(this);
  }

  componentWillMount() {
    this.loadBooks();
  }

  async loadBooks()
  {
    const promise = await axios.get("http://localhost:3000/book");
    const status = promise.status;
    if(status===200)
    {
      const data = promise.data.data;
      this.setState({books:data});
    }
  }

  render() {
    return(
      <div>
        <h1>Books</h1>
            {this.state.books.map((value,index)=>{return <h4 key={index}>{value}</h4>})}
      </div>
    )
  }
}

And modify App.js like this :

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

import { BrowserRouter as Router, Route, Link } from "react-router-dom";

import Book from "./Component/Book/index";

class App extends Component {
  render() {
    return (
      <Router>
        <Route path="/" exact component={Book} />
    </Router>
    );
  }
}

export default App;

All the features of our million dollar book app are complete now!

Navigate to localhost:3000 to see the output :

OPS! Nothing is showing without the word “books”, right?

Open the console of your browser :

We have to solve the CORS issue.

We can solve this issue using django-cors-headers library.

My settings.py solving CORS issue :

"""
Django settings for book project.
Generated by 'django-admin startproject' using Django 2.2.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'w!48u2_5-imo@@1op&r-xle13)k2x0vv(g$@gdif9sc3g(ep&4'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "corsheaders",  # added to solve CORS

    "rest_framework",

    "api",
    "core",
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',  # added to solve CORS
    'django.middleware.common.CommonMiddleware',  # added to solve CORS
    '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 = 'book.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'book-frontend')]
        ,
        '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 = 'book.wsgi.application'

# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators

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',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'


CORS_ORIGIN_ALLOW_ALL = True # added to solve CORS

Now, navigate to localhost:3000 and see our desired output!

Serving React and Django together

This is the key point of this article, we’ll serve these two apps together in the same server.

Create the “build” version of our frontend app

Navigate to the book-frontend directory and run npm run build . This will create a build directory.

Then go to setting.pyand add the following lines :

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'book-frontend')]  #Look, we have added the root folder of frontend here
        ,
        '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',
            ],
        },
    },
]
STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'book-frontend', "build", "static"),  # update the STATICFILES_DIRS
)

Goto cors/view.py now, we will serve our frontend view from here. Update it like :

from django.shortcuts import render


def index(request):
return render(request, "build/index.html")

Update /book/urls.py :

from django.urls import path

from api.views import book

from core.views import index

urlpatterns = [
    path("book/", book, name="book"),
    path("", index, name="index")
]

Now close all the previous servers (if they’re active until now). Run the Django server using python manage.py runserver. Go to your browser and navigate to http://127.0.0.1:8000/ and BOOM! We’re serving our Django and React app in the same server!

#django #reactjs #javascript

Serving React and Django together
3 Likes354.70 GEEK