├── .dockerignore ├── django_backend ├── static │ └── .gitkeep ├── templates │ └── .gitkeep ├── django_backend │ ├── __init__.py │ ├── settings │ │ ├── prod.py │ │ ├── __init__.py │ │ ├── example_env │ │ ├── dev.py │ │ ├── docker.py │ │ └── base.py │ ├── asgi.py │ ├── wsgi.py │ └── urls.py ├── requirements.txt ├── .dockerignore ├── entrypoint.sh ├── Dockerfile ├── manage.py └── .gitignore ├── react_frontend ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── .dockerignore ├── src │ ├── setupTests.js │ ├── App.test.js │ ├── index.css │ ├── reportWebVitals.js │ ├── App.js │ ├── index.js │ ├── App.css │ └── logo.svg ├── .gitignore ├── Dockerfile ├── package.json └── README.md ├── .readme_assets ├── Nginx.png ├── React.png ├── Django.png ├── Docker.png └── PostgreSQL.png ├── nginx ├── Dockerfile └── nginx.conf ├── example_env ├── .gitignore ├── LICENSE ├── docker-compose.yml └── Readme.md /.dockerignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_backend/static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_backend/templates/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_backend/django_backend/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_backend/django_backend/settings/prod.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_backend/django_backend/settings/__init__.py: -------------------------------------------------------------------------------- 1 | from .docker import * -------------------------------------------------------------------------------- /react_frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /.readme_assets/Nginx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ceci-Aguilera/react_django_boilerplate/HEAD/.readme_assets/Nginx.png -------------------------------------------------------------------------------- /.readme_assets/React.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ceci-Aguilera/react_django_boilerplate/HEAD/.readme_assets/React.png -------------------------------------------------------------------------------- /.readme_assets/Django.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ceci-Aguilera/react_django_boilerplate/HEAD/.readme_assets/Django.png -------------------------------------------------------------------------------- /.readme_assets/Docker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ceci-Aguilera/react_django_boilerplate/HEAD/.readme_assets/Docker.png -------------------------------------------------------------------------------- /.readme_assets/PostgreSQL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ceci-Aguilera/react_django_boilerplate/HEAD/.readme_assets/PostgreSQL.png -------------------------------------------------------------------------------- /react_frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ceci-Aguilera/react_django_boilerplate/HEAD/react_frontend/public/favicon.ico -------------------------------------------------------------------------------- /react_frontend/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ceci-Aguilera/react_django_boilerplate/HEAD/react_frontend/public/logo192.png -------------------------------------------------------------------------------- /react_frontend/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ceci-Aguilera/react_django_boilerplate/HEAD/react_frontend/public/logo512.png -------------------------------------------------------------------------------- /nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:latest 2 | 3 | RUN rm /etc/nginx/conf.d/default.conf 4 | COPY nginx.conf /etc/nginx/conf.d 5 | 6 | WORKDIR /usr/src/app -------------------------------------------------------------------------------- /react_frontend/.dockerignore: -------------------------------------------------------------------------------- 1 | .log 2 | npm-debug.log* 3 | yarn-debug.log* 4 | yarn-error.log* 5 | /react_frontend/node_modules 6 | /react_frontend/.pnp 7 | .pnp.js -------------------------------------------------------------------------------- /react_frontend/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /django_backend/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.5.0 2 | backports.zoneinfo==0.2.1 3 | Django==4.0.4 4 | django-cors-headers==3.11.0 5 | django-environ==0.8.1 6 | djangorestframework==3.13.1 7 | gunicorn==20.1.0 8 | Pillow==9.1.0 9 | psycopg2-binary==2.8.6 10 | pytz==2022.1 11 | sqlparse==0.4.2 12 | -------------------------------------------------------------------------------- /react_frontend/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /example_env: -------------------------------------------------------------------------------- 1 | COMPOSE_PROJECT_NAME=ceci_aguilera_react_django_nginx_postgresql 2 | 3 | ENV_API_SERVER=http://127.0.0.1 4 | 5 | POSTGRES_USER=docker 6 | POSTGRES_PASSWORD=SuperDockerPassword5432!!! 7 | POSTGRES_DB=docker 8 | 9 | # If you already have the port 3306 in use, you can change it (for example if you have MySQL) 10 | HOST_MACHINE_MYSQL_PORT=5432 -------------------------------------------------------------------------------- /django_backend/django_backend/settings/example_env: -------------------------------------------------------------------------------- 1 | SECRET_KEY='secret' 2 | 3 | DB_NAME='django_db' 4 | DB_USER='django_user' 5 | DB_PASSWORD='SuperDjangoPassword5432!!!' 6 | DB_HOST='localhost' 7 | DB_PORT=5432 8 | 9 | DB_DOCKER_NAME='docker' 10 | DB_DOCKER_USER='docker' 11 | DB_DOCKER_PASSWORD='SuperDockerPassword5432!!!' 12 | DB_DOCKER_HOST='database' 13 | DB_DOCKER_PORT=5432 -------------------------------------------------------------------------------- /react_frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /django_backend/.dockerignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .env 3 | *.pyc 4 | *.pyo 5 | env/ 6 | venv/ 7 | .venv/ 8 | env* 9 | dist/ 10 | build/ 11 | *.egg 12 | *.egg-info/ 13 | _mailinglist 14 | .tox/ 15 | .cache/ 16 | .pytest_cache/ 17 | .idea/ 18 | docs/_build/ 19 | .vscode 20 | .env 21 | 22 | uploads/** 23 | !uploads/.gitkeep 24 | # Coverage reports 25 | htmlcov/ 26 | .coverage 27 | .coverage.* 28 | *,cover 29 | 30 | migrations/** 31 | !migrations/.gitkeep -------------------------------------------------------------------------------- /react_frontend/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /react_frontend/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | /backend/db.sqlite3 3 | .DS_Store 4 | .env 5 | */settings/local.py 6 | /static/* 7 | /media/* 8 | __pycache__/ 9 | /.vscode/ 10 | 11 | # coverage result 12 | .coverage 13 | /coverage/ 14 | 15 | # pycharm 16 | .idea/ 17 | 18 | # data 19 | *.dump 20 | 21 | # npm 22 | node_modules/ 23 | npm-debug.log 24 | 25 | # Webpack 26 | /frontend/bundles/* 27 | /frontend/webpack_bundles/* 28 | /webpack-stats.json 29 | 30 | 31 | .direnv 32 | .envrc 33 | .tool-versions -------------------------------------------------------------------------------- /django_backend/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | echo "Waiting for postgres to connect ..." 5 | 6 | while ! nc -z database 5432; do 7 | sleep 0.1 8 | done 9 | 10 | echo "PostgreSQL is active" 11 | 12 | python manage.py collectstatic --noinput 13 | python manage.py migrate 14 | python manage.py makemigrations 15 | 16 | gunicorn django_backend.wsgi:application --bind 0.0.0.0:8000 17 | 18 | 19 | 20 | echo "Postgresql migrations finished" 21 | 22 | python manage.py runserver -------------------------------------------------------------------------------- /django_backend/django_backend/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for django_backend project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_backend.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /django_backend/django_backend/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for django_backend project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_backend.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /django_backend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9.5-slim-buster 2 | 3 | WORKDIR /usr/src/app 4 | 5 | ENV PYTHONDONTWRITEBYTECODE 1 6 | ENV PYTHONUNBUFFERED 1 7 | 8 | RUN apt-get update \ 9 | && apt-get install -yyq netcat 10 | 11 | RUN apt-get update \ 12 | && apt-get install -y apt-utils gcc g++ tree 13 | 14 | RUN pip3 install --upgrade pip 15 | COPY ./requirements.txt /usr/src/app/requirements.txt 16 | RUN pip3 install -r requirements.txt 17 | 18 | COPY . /usr/src/app/ 19 | 20 | RUN chmod +x entrypoint.sh 21 | 22 | CMD ["./entrypoint.sh"] -------------------------------------------------------------------------------- /django_backend/django_backend/settings/dev.py: -------------------------------------------------------------------------------- 1 | import environ 2 | from .base import * 3 | 4 | DEBUG = True 5 | 6 | env = environ.Env() 7 | # reading env file 8 | environ.Env.read_env() 9 | 10 | SECRET_KEY= env("SECRET_KEY") 11 | 12 | CORS_ALLOWED_ORIGINS = [ 13 | "http://localhost:3000", 14 | ] 15 | 16 | DATABASES = { 17 | 'default': { 18 | 'ENGINE': 'django.db.backends.postgresql_psycopg2', 19 | 'NAME': env('DB_NAME'), 20 | 'USER': env('DB_USER'), 21 | 'PASSWORD': env('DB_PASSWORD'), 22 | 'HOST': env('DB_HOST'), 23 | 'PORT': env('DB_PORT'), 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /react_frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /django_backend/django_backend/settings/docker.py: -------------------------------------------------------------------------------- 1 | import environ 2 | from .base import * 3 | 4 | DEBUG = True 5 | 6 | env = environ.Env() 7 | # reading env file 8 | environ.Env.read_env() 9 | 10 | SECRET_KEY= env("SECRET_KEY") 11 | 12 | CORS_ALLOWED_ORIGINS = [ 13 | "http://localhost:80", 14 | ] 15 | 16 | DATABASES = { 17 | 'default': { 18 | 'ENGINE': 'django.db.backends.postgresql_psycopg2', 19 | 'NAME': env('DB_DOCKER_NAME'), 20 | 'USER': env('DB_DOCKER_USER'), 21 | 'PASSWORD': env('DB_DOCKER_PASSWORD'), 22 | 'HOST': env('DB_DOCKER_HOST'), 23 | 'PORT': env('DB_DOCKER_PORT'), 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /react_frontend/src/App.js: -------------------------------------------------------------------------------- 1 | import logo from './logo.svg'; 2 | import './App.css'; 3 | 4 | function App() { 5 | return ( 6 |
7 |
8 | logo 9 |

10 | Edit src/App.js and save to reload. 11 |

12 | 18 | Learn React 19 | 20 |
21 |
22 | ); 23 | } 24 | 25 | export default App; 26 | -------------------------------------------------------------------------------- /react_frontend/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | import 'bootstrap/dist/css/bootstrap.min.css'; 8 | 9 | const root = ReactDOM.createRoot(document.getElementById('root')); 10 | root.render( 11 | 12 | 13 | 14 | ); 15 | 16 | // If you want to start measuring performance in your app, pass a function 17 | // to log results (for example: reportWebVitals(console.log)) 18 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 19 | reportWebVitals(); 20 | -------------------------------------------------------------------------------- /react_frontend/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /django_backend/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_backend.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /react_frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:14.19-alpine3.15 as BUILDER 2 | 3 | WORKDIR /usr/src/app 4 | 5 | RUN apk update && apk add tzdata 6 | ENV TZ America/New_York 7 | ENV PATH /usr/app/node_modules/.bin:$PATH 8 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 9 | 10 | RUN apk update && apk add vim 11 | 12 | COPY package.json package-lock.json ./ 13 | 14 | RUN npm install --silent 15 | RUN npm install react-scripts -g --silent 16 | 17 | COPY . . 18 | 19 | ARG API_SERVER 20 | 21 | ENV REACT_APP_API_SERVER=${API_SERVER} 22 | RUN REACT_APP_API_SERVER=${API_SERVER} \ 23 | npm run build 24 | 25 | 26 | 27 | 28 | FROM node:14.19-alpine3.15 29 | 30 | WORKDIR /usr/src/app 31 | 32 | RUN npm install -g serve 33 | 34 | COPY --from=BUILDER /usr/src/app/build ./build -------------------------------------------------------------------------------- /react_frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.4", 7 | "@testing-library/react": "^13.0.1", 8 | "@testing-library/user-event": "^13.5.0", 9 | "axios": "^0.26.1", 10 | "bootstrap": "^5.1.3", 11 | "react": "^18.0.0", 12 | "react-bootstrap": "^2.2.3", 13 | "react-dom": "^18.0.0", 14 | "react-scripts": "5.0.1", 15 | "web-vitals": "^2.1.4" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test", 21 | "eject": "react-scripts eject" 22 | }, 23 | "eslintConfig": { 24 | "extends": [ 25 | "react-app", 26 | "react-app/jest" 27 | ] 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.2%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Cecilia Fernandez Aguilera 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 19 | OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /django_backend/django_backend/urls.py: -------------------------------------------------------------------------------- 1 | """django_backend URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/4.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | from django.urls import re_path as url, include 19 | from django.conf import settings 20 | from django.conf.urls.static import static 21 | from django.views.static import serve 22 | from django.conf.urls.static import static 23 | 24 | urlpatterns = [ 25 | path('admin/', admin.site.urls), 26 | ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) 27 | -------------------------------------------------------------------------------- /nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | upstream django_backend { 2 | server backend:8000; 3 | } 4 | 5 | upstream react_frontend { 6 | server frontend:3000; 7 | } 8 | 9 | server { 10 | 11 | listen 80; 12 | 13 | ########### 14 | # URL ROUTING # 15 | ########### 16 | 17 | location /admin { 18 | proxy_pass http://django_backend; 19 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 20 | proxy_set_header Host $host; 21 | proxy_redirect off; 22 | } 23 | 24 | location /api { 25 | proxy_pass http://django_backend; 26 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 27 | proxy_set_header Host $host; 28 | proxy_redirect off; 29 | } 30 | 31 | ########### 32 | # STATIC FOLDER ROUTING # 33 | ########### 34 | 35 | location /static/admin/ { 36 | alias /usr/src/app/django_files/static/admin/; 37 | } 38 | 39 | location /static/rest_framework/ { 40 | alias /usr/src/app/django_files/static/rest_framework/; 41 | } 42 | 43 | location /static/ { 44 | alias /usr/src/app/react_files/static/; 45 | } 46 | 47 | location /media/ { 48 | alias /usr/src/app/media/; 49 | } 50 | 51 | ########### 52 | # URL ROUTING # 53 | ########### 54 | 55 | location / { 56 | proxy_pass http://react_frontend; 57 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 58 | proxy_set_header Host $host; 59 | proxy_redirect off; 60 | } 61 | 62 | 63 | } -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | services: 4 | backend: 5 | build: 6 | context: ./django_backend 7 | dockerfile: Dockerfile 8 | volumes: 9 | - django_static_volume:/usr/src/app/static 10 | - django_media_volume:/usr/src/app/media 11 | hostname: backend 12 | expose: 13 | - 8000 14 | command: ./entrypoint.sh 15 | links: 16 | - database 17 | database: 18 | image: postgres:13-alpine 19 | volumes: 20 | - postgres_data:/var/lib/postgresql/data/ 21 | restart: 'always' 22 | environment: 23 | POSTGRES_DB: ${POSTGRES_DB} 24 | POSTGRES_USER: ${POSTGRES_USER} 25 | POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} 26 | ports: 27 | - 5432:5432 28 | frontend: 29 | build: 30 | context: ./react_frontend 31 | dockerfile: Dockerfile 32 | args: 33 | - API_SERVER=${ENV_API_SERVER} 34 | volumes: 35 | - react_static_volume:/usr/src/app/build/static 36 | hostname: frontend 37 | expose: 38 | - 3000 39 | env_file: 40 | - .env 41 | command: serve -s build -l 3000 42 | links: 43 | - backend 44 | 45 | nginx: 46 | restart: always 47 | build: ./nginx 48 | volumes: 49 | - django_static_volume:/usr/src/app/django_files/static 50 | - django_media_volume:/usr/src/app/media 51 | - react_static_volume:/usr/src/app/react_files/static 52 | ports: 53 | - 80:80 54 | links: 55 | - frontend 56 | 57 | 58 | volumes: 59 | postgres_data: 60 | django_static_volume: 61 | django_media_volume: 62 | react_static_volume: -------------------------------------------------------------------------------- /react_frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /react_frontend/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_backend/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/django 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=django 3 | 4 | ### Django ### 5 | *.log 6 | *.pot 7 | *.pyc 8 | __pycache__/ 9 | local_settings.py 10 | db.sqlite3 11 | db.sqlite3-journal 12 | media 13 | 14 | # If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/ 15 | # in your Git repository. Update and uncomment the following line accordingly. 16 | # /staticfiles/ 17 | 18 | ### Django.Python Stack ### 19 | # Byte-compiled / optimized / DLL files 20 | *.py[cod] 21 | *$py.class 22 | 23 | # C extensions 24 | *.so 25 | 26 | # Distribution / packaging 27 | .Python 28 | build/ 29 | develop-eggs/ 30 | dist/ 31 | downloads/ 32 | eggs/ 33 | .eggs/ 34 | parts/ 35 | sdist/ 36 | var/ 37 | wheels/ 38 | pip-wheel-metadata/ 39 | share/python-wheels/ 40 | *.egg-info/ 41 | .installed.cfg 42 | *.egg 43 | MANIFEST 44 | 45 | # PyInstaller 46 | # Usually these files are written by a python script from a template 47 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 48 | *.manifest 49 | *.spec 50 | 51 | # Installer logs 52 | pip-log.txt 53 | pip-delete-this-directory.txt 54 | 55 | # Unit test / coverage reports 56 | htmlcov/ 57 | .tox/ 58 | .nox/ 59 | .coverage 60 | .coverage.* 61 | .cache 62 | nosetests.xml 63 | coverage.xml 64 | *.cover 65 | *.py,cover 66 | .hypothesis/ 67 | .pytest_cache/ 68 | pytestdebug.log 69 | 70 | # Translations 71 | *.mo 72 | 73 | # Django stuff: 74 | 75 | # Flask stuff: 76 | instance/ 77 | .webassets-cache 78 | 79 | # Scrapy stuff: 80 | .scrapy 81 | 82 | # Sphinx documentation 83 | docs/_build/ 84 | doc/_build/ 85 | 86 | # PyBuilder 87 | target/ 88 | 89 | # Jupyter Notebook 90 | .ipynb_checkpoints 91 | 92 | # IPython 93 | profile_default/ 94 | ipython_config.py 95 | 96 | # pyenv 97 | .python-version 98 | 99 | # pipenv 100 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 101 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 102 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 103 | # install all needed dependencies. 104 | #Pipfile.lock 105 | 106 | # poetry 107 | #poetry.lock 108 | 109 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 110 | __pypackages__/ 111 | 112 | # Celery stuff 113 | celerybeat-schedule 114 | celerybeat.pid 115 | 116 | # SageMath parsed files 117 | *.sage.py 118 | 119 | # Environments 120 | .env 121 | .env/ 122 | .venv/ 123 | env/ 124 | venv/ 125 | ENV/ 126 | env.bak/ 127 | venv.bak/ 128 | pythonenv* 129 | 130 | # Spyder project settings 131 | .spyderproject 132 | .spyproject 133 | 134 | # Rope project settings 135 | .ropeproject 136 | 137 | # mkdocs documentation 138 | /site 139 | 140 | # mypy 141 | .mypy_cache/ 142 | .dmypy.json 143 | dmypy.json 144 | 145 | # Pyre type checker 146 | .pyre/ 147 | 148 | # pytype static type analyzer 149 | .pytype/ 150 | 151 | # operating system-related files 152 | # file properties cache/storage on macOS 153 | *.DS_Store 154 | # thumbnail cache on Windows 155 | Thumbs.db 156 | 157 | # profiling data 158 | .prof -------------------------------------------------------------------------------- /react_frontend/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 39 | 40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /django_backend/django_backend/settings/base.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for django_backend project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.0.4. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.0/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | import os 16 | 17 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 18 | BASE_DIR = Path(__file__).resolve().parent.parent 19 | ROOT_BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 20 | 21 | TEMPLATES_DIR = os.path.join(ROOT_BASE_DIR,'templates') 22 | 23 | # Quick-start development settings - unsuitable for production 24 | # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ 25 | 26 | # SECURITY WARNING: keep the secret key used in production secret! 27 | 28 | 29 | # SECURITY WARNING: don't run with debug turned on in production! 30 | DEBUG = True 31 | 32 | ALLOWED_HOSTS = ["localhost", "127.0.0.1", "0.0.0.0"] 33 | 34 | 35 | # Application definition 36 | 37 | INSTALLED_APPS = [ 38 | 'django.contrib.admin', 39 | 'django.contrib.auth', 40 | 'django.contrib.contenttypes', 41 | 'django.contrib.sessions', 42 | 'django.contrib.messages', 43 | 'django.contrib.staticfiles', 44 | "corsheaders", 45 | "rest_framework", 46 | ] 47 | 48 | MIDDLEWARE = [ 49 | "corsheaders.middleware.CorsMiddleware", 50 | 'django.middleware.security.SecurityMiddleware', 51 | 'django.contrib.sessions.middleware.SessionMiddleware', 52 | 'django.middleware.common.CommonMiddleware', 53 | 'django.middleware.csrf.CsrfViewMiddleware', 54 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 55 | 'django.contrib.messages.middleware.MessageMiddleware', 56 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 57 | ] 58 | 59 | ROOT_URLCONF = 'django_backend.urls' 60 | 61 | TEMPLATES = [ 62 | { 63 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 64 | 'DIRS': [TEMPLATES_DIR, ], 65 | 'APP_DIRS': True, 66 | 'OPTIONS': { 67 | 'context_processors': [ 68 | 'django.template.context_processors.debug', 69 | 'django.template.context_processors.request', 70 | 'django.contrib.auth.context_processors.auth', 71 | 'django.contrib.messages.context_processors.messages', 72 | ], 73 | }, 74 | }, 75 | ] 76 | 77 | WSGI_APPLICATION = 'django_backend.wsgi.application' 78 | 79 | 80 | # Database 81 | # https://docs.djangoproject.com/en/4.0/ref/settings/#databases 82 | 83 | 84 | 85 | # Password validation 86 | # https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators 87 | 88 | AUTH_PASSWORD_VALIDATORS = [ 89 | { 90 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 91 | }, 92 | { 93 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 94 | }, 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 97 | }, 98 | { 99 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 100 | }, 101 | ] 102 | 103 | 104 | # Internationalization 105 | # https://docs.djangoproject.com/en/4.0/topics/i18n/ 106 | 107 | LANGUAGE_CODE = 'en-us' 108 | 109 | TIME_ZONE = 'UTC' 110 | 111 | USE_I18N = True 112 | 113 | USE_TZ = True 114 | 115 | 116 | # Static files (CSS, JavaScript, Images) 117 | # https://docs.djangoproject.com/en/4.0/howto/static-files/ 118 | 119 | STATIC_URL = 'static/' 120 | 121 | STATICFILES_DIR = [os.path.join(ROOT_BASE_DIR,'static')] 122 | STATIC_ROOT = os.path.join(ROOT_BASE_DIR,'static') 123 | 124 | 125 | MEDIA_URL = '/media/' 126 | MEDIA_ROOT = os.path.join(ROOT_BASE_DIR, 'media') 127 | 128 | # Default primary key field type 129 | # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field 130 | 131 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 132 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # React Django Boilerplate 4 | 5 | ![Python version](https://img.shields.io/badge/Python-3.10.8-4c566a?logo=python&&longCache=true&logoColor=white&colorB=pink&style=flat-square&colorA=4c566a) ![Django version](https://img.shields.io/badge/Django-4.0.4-4c566a?logo=django&&longCache=truelogoColor=white&colorB=pink&style=flat-square&colorA=4c566a) ![Django-RestFramework version](https://img.shields.io/badge/Django_Rest_Framework-3.13.1-red.svg?longCache=true&style=flat-square&logo=django&logoColor=white&colorA=4c566a&colorB=pink) ![PostgreSQL version](https://img.shields.io/badge/PostgreSQL-12.8-red.svg?longCache=true&style=flat-square&logo=postgresql&logoColor=white&colorA=4c566a&colorB=pink) ![React version](https://img.shields.io/badge/React-18.0.0-red.svg?longCache=true&style=flat-square&logo=react&logoColor=white&colorA=4c566a&colorB=pink) 6 | 7 | ![React Image](./.readme_assets/React.png) ![Django Image](./.readme_assets/Django.png) ![Nginx Image](./.readme_assets/Nginx.png) ![PostgreSQL Image](./.readme_assets/PostgreSQL.png) ![Docker Image](./.readme_assets/Docker.png) 8 | 9 | 10 |
11 | 12 | ## Table of Contents 13 | 1. [Description](#description) 14 | 1. [Tech Stack and Packages Installed](#tech_stack) 15 | 1. [Install (Run) with Docker](#docker) 16 | 1. [Install without Docker](#install) 17 | 1. [Structure for Docker-Compose Explained](#structure) 18 | 1. [Django Files and Folders of Interest](#django) 19 | 1. [React Files and Folders of Interest](#react) 20 | 1. [About Nginx Configuration](#nginx) 21 | 1. [Useful Links](#useful_links) 22 | 1. [Contributing](#contributing) 23 | 24 | 25 | ## Description 26 | 27 | This repository contains a simple boilerplate project setup for Django + React applications. It is intended to have the minimal amount of packages installed by default, and it has a ready-to-test default configuration for Docker. 28 | 29 | For example, see [Fullstack Web Home Key Renovations](https://github.com/Ceci-Aguilera/fullstack-web-home-key-renovations). Home Key Renovations (HKR) is a fullstack website that has this repository as base template. 30 | 31 | 32 | ## Tech Stack and Packages Installed 33 | 34 | - __Django:__ This is the backbone of the backend api, and has the following packages installed: 35 | - Django Rest Framework (For the Rest API) 36 | - Pillow (For managing images uploading) 37 | - Django-Cors-Headers (For the CORS config to allow React js to make calls) 38 | - Django-Environ (To Fetch the environment variables in the settings.py files) 39 | - Psycopg2-binary (To manage the PostgreSQL Database) 40 | - Gunicorn (To manage the running instance of the django web app) 41 | 42 | __Note:__ All this packages are specified in the _requirements.txt_ file inside the __django_backend__ folder. Links to their official documentation can be found at the [Useful Links](#useful_links) section. 43 | 44 | - __React:__ The frontend library in use. This was created via ``npx create-react-app``. The only extra packages that were installed (ignoring the ones that are automatically pre-installed) are: 45 | - Bootstrap and React-Bootstrap (For styling) 46 | - Axios (To make calls to the Django Backend) 47 | 48 | __Note:__ The bootstrap css link has been added to the index.js file that is inside the __react_frontend/src__ folder. The links to the official documentation of these packages is included in the [Useful Links](#useful_links) section. 49 | 50 | - __Nginx:__ This is the server for the Docker-Compose testing build. The default configuration in use can be found at the __nginx/nginx.conf__ file. 51 | 52 | - __PostgreSQL:__ This is the default configured database for this repository. A link to _How to install/configure it for Linux/Windows/MacOS_ is included in the [Useful Links](#useful_links) section (This is only necessary for when not running with docker-compose). In addition, a link to _How to change to MySQL in Django_ is included as well in the [Useful Links](#useful_links) section. 53 | 54 | 55 | ## Install (Run) with Docker 56 | 57 | 1. Clone the repo: 58 | ```bash 59 | git clone https://github.com/Ceci-Aguilera/react_django_boilerplate.git 60 | ``` 61 | 1. Copy a default setup of the environment variables for the project: 62 | ```bash 63 | cp example_env .env 64 | cp django_backend/django_backend/settings/example_env django_backend/django_backend/settings/.env 65 | ``` 66 | 1. (optional) Edit the values in the previous copied files to create a custom config. Note that the one set by default should work just fine for development. 67 | 1. Run Docker-Compose: 68 | ```bash 69 | docker-compose up -d --build 70 | ``` 71 | 72 | Congratulations !!! The app should be up and running. To access the __React__ frontend go to [localhost:80](http://localhost:80), and to access the __Django__ backend go to [localhost:80/api](http://localhost:80/api). From now on, any call made to [localhost:80/api](http://localhost:80/api) will be redirected to __Django__ while every other path (localhost:80/*) will lead to the __React__ frontend, with [localhost:80/admin](http://localhost:80/admin) being the only exception ([localhost:80/admin](http://localhost:80/admin) is an special url path that redirects to the Django Admin). In other words, the urls [localhost:80/api](http://localhost:80/api/*) and [localhost:80/admin](http://localhost:80/api) are reserved for the __Django__ backend, while any other url of the form [localhost:80/*](http://localhost:80/*) redirects to the __React__ frontend. 73 | 74 | 1. (optional) To create a super user: 75 | ```bash 76 | docker-compose run backend ./manage.py createsuperuser 77 | ``` 78 | 79 | 80 | ## Install without Docker 81 | 82 | 1. Clone the repo: 83 | ```bash 84 | git clone https://github.com/Ceci-Aguilera/react_django_boilerplate.git 85 | ``` 86 | 87 | 1. Copy a default configuration of the environment variables for Django: 88 | ```bash 89 | cp django_backend/django_backend/settings/example_env django_backend/django_backend/settings/.env 90 | ``` 91 | 1. (optional) Edit the values in the previous file that was copied to create a custom config. Note that the one set by default should work just fine for development. 92 | 93 | 1. Set up the database. In this case the one in use by default is PostgreSQL. Assuming that PostgreSQL is already installed in the OS, and that the needed configurations for PostgreSQL to run in the OS are done, create a database and an user using the credentials specified in the __django_backend/django_backend/settings/.env__ file that was just created/edited. 94 | __Note:__ To now how to install and configure PostgreSQL, see the [Useful Links](#useful_links) section of this documentation. 95 | 96 | 1. Change the default settings.py file in use from docker to development. To do this, go to the file __django_backend/django_backend/settings/\_\_init\_\_.py__ and modify the line 97 | ```python 98 | from .docker import * 99 | ``` 100 | to 101 | ```python 102 | from .dev import * 103 | ``` 104 | 105 | 1. Create and activate a virtual environment (See the [Useful Links](#useful_links) section if not know how) 106 | 107 | 1. Install the necessary dependencies 108 | ```bash 109 | cd django_backend 110 | pip install -r requirements.txt 111 | ``` 112 | 113 | 1. Run Django: 114 | ```bash 115 | cd django_backend 116 | python manage.py makemigrations 117 | python manage.py migrate 118 | python manage.py runserver 119 | ``` 120 | 121 | 1. To configure React, from the project root folder go to __react_frontend__ and install the necessary dependencies: 122 | ```bash 123 | cd react_frontend 124 | npm install 125 | ``` 126 | 127 | 1. (optional) Add django backend url as proxy. To do so go to __react_frontend__ and edit the package.json, in the block before the "devDependencies" block add 128 | ```json 129 | "proxy": "http://localhost:5000/", 130 | ``` 131 | 132 | Now, that section in the package.json should look like the following: 133 | ```json 134 | "development": [ 135 | "last 1 chrome version", 136 | "last 1 firefox version", 137 | "last 1 safari version" 138 | ] 139 | }, 140 | "proxy": "http://localhost:5000/", 141 | "devDependencies": { 142 | "@babel/node": "^7.16.8", 143 | "@babel/plugin-transform-react-jsx": "^7.17.3", 144 | "babel-cli": "^6.26.0", 145 | "babel-preset-es2015": "^6.24.1", 146 | "babel-preset-react": "^6.24.1", 147 | "babel-register": "^6.26.0" 148 | } 149 | ``` 150 | 151 | 1. Run React while inside the __react_frontend__ folder: 152 | ```bash 153 | npm start 154 | ``` 155 | 156 | Congratulations !!! The app should be up and running. To access the __React__ frontend go to [localhost:3000](http://localhost:3000), and to access the __Django__ backend go to [localhost:8000](http://localhost:8000). 157 | 158 | 159 | 160 | ## Structure for Docker-Compose Explained 161 | 162 | This repository is divided into 3 main folders (not counting the .readme_assets as it contains only the images displayed in the Readme). These folders are: 163 | - __django_backend:__ Has the Django project created with ``django-admin startproject``. 164 | - __react_frontend:__ Has the React project create with ``npx create-react-app``. 165 | - __nginx:__ Has the Dockerfile used in the docker-compose.yml file and the default config to run Django + React. When running the project locally without Docker this folder can be ignored. 166 | 167 | Each project (Django and React as separate projects) is intended to be self contained, and so it can be separately tested without the need of docker-compose. 168 | 169 | When running with __Docker Compose__, there are 4 images that are created: A Django backend Image, a React frontend Image, a Nginx Image, and a PostgreSQL Image. The Dockerfiles for Django, React, and Nginx can be found in their respective folders, i.e, the Django Dockerfile is inside the django_backend folder, and so on. The PostgreSQL image has no custom Dockerfile, instead it is pulled from the Docker Hub, and the environment variables for the docker-compose file can be found at the .env file in the project root folder. This repository does not include that file, instead it offers an example_env file that can be renamed to .env and it should work out of the box (the default environment variables set do not need to be modified). 170 | 171 | 172 | ## Django Files and Folders of Interest 173 | So far, there is no app created for Django, and so, the only important folder so far is the settings folder inside the __django_backend/django_backend__ folder. This contains different settings.py files for different environment. For example, the dev.py file has the default settings to run in the development environment, while the docker.py file has the default settings to run when using docker-compose. All of these files has the base.py file as their parent file (the base.py file has the settings to be shared among the environments), and so they all should have 174 | 175 | ```python 176 | from .base import * 177 | ``` 178 | 179 | as their first line. To change between environments, go to the __django_backend/django_backend/\_\_init\_\_.py__ file and edit its first line. By default it should be 180 | 181 | ```python 182 | from .docker import * 183 | ``` 184 | 185 | To change to the environment ``x``, replace that line with 186 | 187 | ```python 188 | from .x import * 189 | ``` 190 | 191 | Next, the __templates__, __static__, and __media__ folders have been created (and configured in the settings) to store the hml, css, ... files. 192 | 193 | 194 | ## React Files and Folders of Interest 195 | 196 | Aside from the __package.json__ and the __src/index.js__ files there are no other edited files in this folder. 197 | 198 | The following structure is used by the owner of this repository when working on a React project, and it was taken from the Next js workflow: 199 | ```text 200 | react_frontend 201 | |___ src 202 | |____ components 203 | |____ pages 204 | |____ styles 205 | |____ assets 206 | ``` 207 | 208 | --- 209 | 210 | 211 | 212 | ## Contributing 213 | 214 | Inputs and contributions to this project are appreciated. To make them as transparent and easy as possible, please follow this steps: 215 | 216 | - ### How to contribute: 217 | 1. Fork the repo and create your branch from master 218 | 1. Clone the project to your own machine 219 | 1. Commit changes to your own branch 220 | 1. Update documentation 221 | 1. Push your work back up to your fork 222 | 1. Submit a Pull request 223 | 224 | #### Don't: 225 | - Don't include any license information when submitting your code as this repository is MIT licensed, and so your submissions are understood to be under the same MIT License as well. 226 | 227 | - ### How to report a bug: 228 | 1. Open a new Issue. 229 | 1. Write a bug report with details, background, and when possible sample code. That's it! 230 | 231 | 232 | 233 | ## Useful Links 234 | 235 | ### PostgreSQL and other Databases 236 | - Install/Setup Database in Linux: [Digital Ocean Link for Django Deployment on VPS](https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04) 237 | - Install/Setup in Windows: [guru99.com Link](https://www.guru99.com/download-install-postgresql.html) 238 | - Install/Setup in MAC OS: [postgresqltutorial.com Link](https://www.postgresqltutorial.com/postgresql-getting-started/install-postgresql-macos/) 239 | - [Django with MySQL](https://dev.to/sm0ke/how-to-use-mysql-with-django-for-beginners-2ni0) 240 | 241 | ### Docker 242 | - [Docker Oficial Documentation](https://docs.docker.com/) 243 | - Dockerizing Django, PostgreSQL, guinicorn, and Nginx: 244 | - Github repo of sunilale0: [Link](https://github.com/sunilale0/django-postgresql-gunicorn-nginx-dockerized/blob/master/README.md#nginx) 245 | - My repo to Dockerize Django + MySQL + Nginx + React js: [Ceci-Aguilera/django-react-nginx-mysql-docker](https://github.com/Ceci-Aguilera/django-react-nginx-mysql-docker) 246 | - Michael Herman article on testdriven.io: [Link](https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/) 247 | ### Django and DRF 248 | - [Django Official Documentation](https://docs.djangoproject.com/en/4.0/) 249 | - Generate a new secret key: [Stackoverflow Link](https://stackoverflow.com/questions/41298963/is-there-a-function-for-generating-settings-secret-key-in-django) 250 | - Modify the Django Admin: 251 | - Small modifications (add searching, columns, ...): [Link](https://realpython.com/customize-django-admin-python/) 252 | - Modify Templates and css: [Link from Medium](https://medium.com/@brianmayrose/django-step-9-180d04a4152c) 253 | - [Django Rest Framework Official Documentation](https://www.django-rest-framework.org/) 254 | - More about Nested Serializers: [Stackoverflow Link](https://stackoverflow.com/questions/51182823/django-rest-framework-nested-serializers) 255 | - More about GenericViews: [Testdriver.io Link](https://testdriven.io/blog/drf-views-part-2/) 256 | - [Django Pillow](https://pillow.readthedocs.io/en/stable/) 257 | - [Django-Cors-Headers](https://pypi.org/project/django-cors-headers/) 258 | - [Django-Environ](https://pypi.org/project/django-environ-2/) 259 | - [Psycopg2-binary](https://pypi.org/project/psycopg2-binary/) 260 | - [Gunicorn](https://pypi.org/project/gunicorn/) 261 | 262 | ### React 263 | - [React Official Documentation](https://reactjs.org/) 264 | - [Create React App Official Documentation](https://create-react-app.dev/) 265 | - [Bootstrap Official Documentation](https://getbootstrap.com/) 266 | - [React-Bootstrap Documentation](https://react-bootstrap.github.io/) 267 | - [Axios Documentation](https://axios-http.com/docs/intro) 268 | 269 | ### Miscellaneous 270 | - Create Virual Environment with Virtualenv and Virtualenvwrapper: [Link](https://docs.python-guide.org/dev/virtualenvs/) 271 | - [Configure CORS](https://www.stackhawk.com/blog/django-cors-guide/) 272 | - [Setup Django with Cloudinary](https://cloudinary.com/documentation/django_integration) 273 | 274 | 275 | 276 | 277 | --------------------------------------------------------------------------------