Tech Incent
DjangoReact

How to deploy django and react in heroku ?

how-to-deploy-django-and-react-in-heroku

There are lots of hosts for setting up Django API and React. but most of them are very complicated processes but there are main two different methodologies:

  • Separate Django back-end and react front-end: In this method, Django and React will be deployed separately. Django server instance will run Django, on other hand, React server instance handle react app. but there are communicate data with API. it’s important to set up a “Cross-Origin Resource Sharing(CORS)” configuration. Most developer development with Django React application with this separate method.
  • Serve with the same host: it’s the best way to deploy small and medium django react applications. you don’t want to spend a good of cost for a small application like a blog, portfolio, business profile, etc.

In this article, we deploy Django and React application (what was created in last article) in the Heroku server. We will serve Django React apps with the same host

Before we go process we need to set up Django and react together, So check the django and react setup

Requirements for deployment

Setting up Django for deployment

Install some package/dependencies for deployment

$ pip install whitenoise gunicorn dj-database-url psycopg2-binary

ALLOW_HOSTS and make false

Edit blisting/blisting/settings.py file

DEBUG = False
ALLOWED_HOSTS = ['.yourappname.herokuapp.com']

Static Files configuration

Most of developer recommend django static files to store in AWS S3. Learn more how to store django static file with AWS S3. But for this tutorial, we serve static files in the same host. keep it in mind. AWS S3 best for serving static files.

Configure whitenoise middleware in blisting/settings.py

MIDDLEWARE = [
  # 'django.middleware.security.SecurityMiddleware',
  'whitenoise.middleware.WhiteNoiseMiddleware',
  # ...
]

Settings up the static file in blisting/settings.py

# https://docs.djangoproject.com/en/3.0/howto/static-files/
REACT_APP_PATH = os.path.join(BASE_DIR, 'frontend')

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

STATICFILES_DIRS = [
    os.path.join(REACT_APP_PATH, 'static')
]
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

make a static directory in the project root directory or blisitng/static

$ mkdir static

Add database config in settings.py for heroku app

add database settings in django “blisting/settings.py” file. make sure DATABASE config is top of this

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
import dj_database_url
db_from_env = dj_database_url.config()
DATABASES['default'].update(db_from_env)
DATABASES['default']['CONN_MAX_AGE'] = 500

Declare runtime for Django

Create a “blisting/runtime.txt” file, I am using python-3.8.3 your case may be different. make sure you declare the right version of yours.

python-3.8.3

Check python runtime

$ python -v

Declare Procfile

create blisting/Procfile in the project root directory

release: python manage.py migrate
web: gunicorn blisting.wsgi

Generate requirements.txt file

$ pip freeze > requirements.txt

how does the project structure look like?

.
├── blisting
│   ├── asgi.py
│   ├── __init__.py
│   ├── __pycache__
│   ├── settings.py
│   ├── urls.py
│   ├── views.py
│   └── wsgi.py
├── db.sqlite3
├── frontend
│   ├── node_modules
│   ├── package.json
│   ├── Procfile
│   ├── public
│   ├── README.md
│   ├── src
│   └── yarn.lock
├── list
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   ├── models.py
│   ├── __pycache__
│   ├── serializers.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── Procfile
├── README.md
├── requirements.txt
├── runtime.txt
├── static
│   ├── admin
│   ├── css
│   ├── js
│   └── rest_framework
├── venv
│   ├── bin
│   ├── include
│   ├── lib
│   └── share

Set up React app

Add proxy in main react blisting/frontend/package.json file

"proxy": "http://localhost:8000"

Serve React in Heroku app

Our project root directory is “blasting”. and you know the React root path is “blisting/frontend” directory. Now the problem is Heroku doesn’t detect frontend react apps. Heroku requires apps will define in the root directory. So How can make we detect react to heroku app?

Method one, we can cut all files and folder and paste in root directory “blasting”, it may some more problem with conflict with django application.

Method Two, On the other and best way, we used it. So follow this direction,
Make a package.json file in root directory “blisting/package.json”

$ touch package.json

configure blisting/package.json file. “engines” configurations may be different for your app. So config with your node and npm version.

{
  "name": "Blisting",
  "version": "1.0.1",
  "description": "Business listing application",
  "main": "index.js",
  "repository": "[email protected]:sajalmia381/django-react-setup.git",
  "author": "Md Sajal Mia <[email protected]>",
  "license": "MIT",
  "private": true,
  "scripts": {
    "heroku-prebuild": "NODE_ENV=production cd frontend/ && yarn install && yarn build && cd .."
  },
  "cacheDirectories": [
    "frontend/node_modules"
  ],
  "engines": {
    "node": "10.20.1",
    "npm": "6.14.5"

  }
}

Make yarn.lock file in the root directory “blisting/yarn.lock”, and leave it blank. heroku automatic install yarn and server all module in this file.

$ touch yarn.lock

Serve react view instant by Django

create django dynamic view that will serve all react views. I am talking about the real project, where are you create this view? Example: creating a “python manage.py startapp core” or create a views.py file in the main root directory blisting/blisting/views.py where it is all core configuration store. in this case, we will create in “blisting/blisting/views.py”

import os
import logging
from django.http import HttpResponse
from django.views.generic import View
from django.conf import settings


class FrontendAppView(View):
    """
    Serves the compiled frontend entry point (only works if you have run `yarn
    build`).
    """
    index_file_path = os.path.join(settings.REACT_APP_DIR, 'build', 'index.html')

    def get(self, request):
        try:
            with open(self.index_file_path) as f:
                return HttpResponse(f.read())
        except FileNotFoundError:
            logging.exception('Production build of app not found')
            return HttpResponse(
                """
                This URL is only used when you have built the production
                version of the app. Visit http://localhost:3000/ instead after
                running `yarn start` on the frontend/ directory
                """,
                status=501,
            )

Add frontend view function to blisting/blisting/urls.py

from django.contrib import admin
from django.urls import path, include, re_path
from .views import FrontendAppView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('list.urls')),
    re_path(r'^', FrontendAppView.as_view()),
]

Set up Heroku server

I hope your machine has a Heroku CLI. and I also hope you have a Heroku account or you can create a Heroku account here.
I am configuration application with terminal instant Heroku CLI  but you can configure with Heroku dashboard.

  1. login with terminal
    $ heroku login
  2. Create heroku apps
    $ heroku apps:create -a blisting
  3. Add buildpack in Heroku, learn more about Heroku buildpack
    $ heroku buildpacks:set heroku/python
    $ heroku buildpacks:add --index 1 heroku/nodejs
    Buildpack added. Next release on blisting will use:
      1. heroku/nodejs
      2. heroku/python
    Run git push heroku master to create a new release using these buildpacks.
  4. Add Postgres database in Heroku app
    $ heroku addons:create heroku-postgresql:hobby-dev
    Creating heroku-postgresql:hobby-dev on ⬢ blisting... free
    Database has been created and is available
     ! This database is empty. If upgrading, you can transfer
     ! data from another database with pg:copy
    Created postgresql-shallow-41905 as DATABASE_URL
    Use heroku addons:docs heroku-postgresql to view documentation
  5. Disable collectstatic file
    $ heroku config:set DISABLE_COLLECTSTATIC=1
  6. You can check configuration
    $ heroku config
  7. So finally push to Heroku
    $ git push heroku master

    buil-success

  8. Build react application and make usable for Django
    $ python manage.py collectstatic

conclusion

 

Related posts

Understanding Django and django design principles

Tech Incent

Explained Django inline formset factory with example?

Sajal Mia

How to set up django react together ?

Sajal Mia

Django Send Email with AWS Simple Email Service(SES)

Sajal Mia

How to delete file when models instance is delete or update in Django?

Sajal Mia

React bootstrap form example

Tech Incent