-
-
Save darkopstech/d92c138e0049e31360a15e773a50a867 to your computer and use it in GitHub Desktop.
make Django project from scratch (in one command).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# README | |
# -------------------- | |
# chmod u+x django_init.sh | |
# ./django_init.sh my-super-project.com main | |
# -------------------- | |
SETTINGS_APP="core" | |
# cat.com | |
PROJECT_NAME="$1" | |
# main | |
MAIN_APP=$2 | |
BACKEND_CONTAINER_NAME="backend" | |
BACKEND_CONTAINER_PORT="8000" | |
NGINX_CONTAINER_NAME="nginx" | |
NGINX_CONTAINER_PORT="80" | |
NGINX_PORT="8080" | |
if [ -z "$PROJECT_NAME" ] | |
then | |
echo "\$PROJECT_NAME is empty. Run this: $0 my-super-project.com main" | |
exit 1 | |
fi | |
if [ -z "$MAIN_APP" ] | |
then | |
echo "\$MAIN_APP is empty. Run this: $0 my-super-project.com main" | |
exit 1 | |
fi | |
show_msg() | |
{ | |
printf "=%.0s" {1..30} | |
printf "\n$1\n" | |
printf "=%.0s" {1..30} | |
printf "\n" | |
} | |
git_init() | |
{ | |
cat <<EOF > .gitignore | |
# Byte-compiled / optimized / DLL files | |
__pycache__/ | |
*.py[cod] | |
*$py.class | |
# C extensions | |
*.so | |
# Distribution / packaging | |
.Python | |
build/ | |
develop-eggs/ | |
dist/ | |
downloads/ | |
eggs/ | |
.eggs/ | |
lib/ | |
lib64/ | |
parts/ | |
sdist/ | |
var/ | |
wheels/ | |
share/python-wheels/ | |
*.egg-info/ | |
.installed.cfg | |
*.egg | |
MANIFEST | |
# PyInstaller | |
# Usually these files are written by a python script from a template | |
# before PyInstaller builds the exe, so as to inject date/other infos into it. | |
*.manifest | |
*.spec | |
# Installer logs | |
pip-log.txt | |
pip-delete-this-directory.txt | |
# Unit test / coverage reports | |
htmlcov/ | |
.tox/ | |
.nox/ | |
.coverage | |
.coverage.* | |
.cache | |
nosetests.xml | |
coverage.xml | |
*.cover | |
*.py,cover | |
.hypothesis/ | |
.pytest_cache/ | |
cover/ | |
# Translations | |
*.mo | |
*.pot | |
# Django stuff: | |
*.log | |
local_settings.py | |
db.sqlite3 | |
db.sqlite3-journal | |
# Flask stuff: | |
instance/ | |
.webassets-cache | |
# Scrapy stuff: | |
.scrapy | |
# Sphinx documentation | |
docs/_build/ | |
# PyBuilder | |
.pybuilder/ | |
target/ | |
# Jupyter Notebook | |
.ipynb_checkpoints | |
# IPython | |
profile_default/ | |
ipython_config.py | |
# pyenv | |
# For a library or package, you might want to ignore these files since the code is | |
# intended to run in multiple environments; otherwise, check them in: | |
# .python-version | |
# pipenv | |
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. | |
# However, in case of collaboration, if having platform-specific dependencies or dependencies | |
# having no cross-platform support, pipenv may install dependencies that don't work, or not | |
# install all needed dependencies. | |
#Pipfile.lock | |
# PEP 582; used by e.g. github.com/David-OConnor/pyflow | |
__pypackages__/ | |
# Celery stuff | |
celerybeat-schedule | |
celerybeat.pid | |
# SageMath parsed files | |
*.sage.py | |
# Environments | |
.env | |
.venv | |
env/ | |
venv/ | |
ENV/ | |
env.bak/ | |
venv.bak/ | |
# Spyder project settings | |
.spyderproject | |
.spyproject | |
# Rope project settings | |
.ropeproject | |
# mkdocs documentation | |
/site | |
# mypy | |
.mypy_cache/ | |
.dmypy.json | |
dmypy.json | |
# Pyre type checker | |
.pyre/ | |
# pytype static type analyzer | |
.pytype/ | |
# Cython debug symbols | |
cython_debug/ | |
.idea | |
EOF | |
show_msg "git: init" | |
git init | |
git branch -m main | |
show_msg "git: commit all" | |
git add . | |
git commit -m 'init commit' | |
} | |
rm -rf $PROJECT_NAME | |
mkdir $PROJECT_NAME && cd $PROJECT_NAME | |
show_msg "create project: $PROJECT_NAME" | |
virtualenv venv | |
source venv/bin/activate | |
show_msg "install django" | |
pip install django | |
mkdir src && cd src | |
show_msg "create main app: $SETTINGS_APP" | |
django-admin startproject $SETTINGS_APP . | |
show_msg "create app: $MAIN_APP" | |
django-admin startapp $MAIN_APP | |
show_msg "install dependencies" | |
###### desired dependencies | |
pip install django_extensions | |
pip install django-debug-toolbar | |
pip install flake8 | |
pip install requests | |
pip install celery | |
###### Optional dependencies | |
pip install psycopg2-binary | |
pip install redis | |
pip install djangorestframework | |
pip install django-filter | |
pip install drf-yasg | |
pip install gunicorn | |
pip install python-memcached | |
show_msg "freeze" | |
cd .. | |
pip freeze > requirements.txt | |
show_msg "prepare settings" | |
# INSTALLED_APPS | |
_apps=( | |
'django.contrib.staticfiles' | |
'django_extensions' | |
'main' | |
) | |
apps=$(printf ' '"'"'%s'"'"',\\n' "${_apps[@]}") | |
apps=${apps:1} | |
sed -i -e "s/ 'django.contrib.staticfiles',/ $apps/g" "src/$SETTINGS_APP/settings.py" | |
show_msg "create necessary files (templates, configs, Makefile, Dockerfile etc)" | |
mkdir -p "src/$MAIN_APP/templates/$MAIN_APP" | |
touch "src/$MAIN_APP/templates/$MAIN_APP/base.html" | |
touch "src/$MAIN_APP/templates/$MAIN_APP/index.html" | |
cat <<EOF > src/$MAIN_APP/templates/$MAIN_APP/base.html | |
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
<title>Home page</title> | |
</head> | |
<body> | |
{% block content %}{% endblock %} | |
</body> | |
</html> | |
EOF | |
cat <<EOF > src/$MAIN_APP/templates/$MAIN_APP/index.html | |
{% extends 'main/base.html' %} | |
{% block content %} | |
<h1>Hello from Django App</h1> | |
{% endblock %} | |
EOF | |
cat <<EOF > src/$SETTINGS_APP/urls.py | |
from django.contrib import admin | |
from django.urls import path, include | |
urlpatterns = [ | |
path('admin/', admin.site.urls), | |
path('', include('main.urls')), | |
] | |
EOF | |
cat <<EOF > src/$MAIN_APP/urls.py | |
from django.urls import path | |
from django.views.generic import TemplateView | |
urlpatterns = [ | |
# path('', views.index, name='home_page'), | |
path('', TemplateView.as_view(template_name='main/index.html'), name='home_page'), | |
] | |
EOF | |
touch .env | |
cat <<EOF > .flake8 | |
[flake8] | |
max-line-length=120 | |
inline-quotes=" | |
max-complexity=10 | |
import-order-style=google | |
ignore=Q000,D103,D100,A003,D107,D105,D101,D106, D104 | |
EOF | |
cat <<EOF > Makefile | |
include .env | |
export $(shell sed 's/=.*//' .env) | |
MANAGE=python src/manage.py | |
PROJECT_DIR=\$(shell pwd) | |
WSGI_PORT=$BACKEND_CONTAINER_PORT | |
RUN_COMMAND=run | |
BACKEND_CONTAINER=$BACKEND_CONTAINER_NAME | |
NGINX_CONTAINER=$NGINX_CONTAINER_NAME | |
help : Makefile | |
@echo "+--------------------+" | |
@echo "| AVAILABLE COMMANDS |" | |
@echo "+--------------------+\n" | |
@echo "REGULAR\n" | |
@cat Makefile | grep "##" | grep -v "docker" | sed -n 's/^## /make /p' | column -t -s ':' && echo "" | |
@echo "DOCKER\n" | |
@cat Makefile | grep "##" | grep "docker" | sed -n 's/^## /make /p' | column -t -s ':' && echo "" | |
## run: run local server. | |
run: | |
\$(MANAGE) runserver 0.0.0.0:\$(WSGI_PORT) | |
## run-now: run local server and open it in browser. | |
run-now: | |
make run& | |
open "http://127.0.0.1:\$(WSGI_PORT)" | |
## gunicorn-run: run gunicorn server. | |
gunicorn-run: | |
gunicorn -w 4 -b 0.0.0.0:\$(WSGI_PORT) --chdir \$(PROJECT_DIR)/src $SETTINGS_APP.wsgi --timeout 60 --log-level debug --max-requests 10000 | |
## new-migrate: create new migration files by changes in models. | |
new-migrate: | |
\$(MANAGE) makemigrations | |
## migrate: apply migrations to storage (DB). | |
migrate: | |
\$(MANAGE) migrate | |
## check: check Django project. | |
check: | |
\$(MANAGE) check | |
## check-migrate: check Django migrations. | |
check-migrate: | |
\$(MANAGE) makemigrations --check --dry-run | |
## lint: do static code analyse. | |
lint: | |
flake8 . | |
## shell: open Django shell with autoloading of the apps database models and subclasses of user-defined classes. | |
shell: | |
\$(MANAGE) shell_plus --print-sql | |
## createsuperuser: open django prompt to add new super user. | |
createsuperuser: | |
\$(MANAGE) createsuperuser | |
## collect-static: store static in server. | |
collect-static: | |
\$(MANAGE) collectstatic | |
## freeze: freeze project dependencies into file - requirements.txt. | |
freeze: | |
pip freeze > requirements.txt | |
## docker-run: run app with Django dev server (runserver). | |
docker-run: docker-down | |
\$(eval RUN_COMMAND=run) | |
docker-compose up -d --build | |
#make docker-copy-static | |
## docker-run-gunicorn: run gunicorn server. | |
docker-run-gunicorn: docker-down | |
\$(eval RUN_COMMAND=gunicorn-run) | |
docker-compose up -d --build | |
## docker-down: stop containers. | |
docker-down: | |
docker-compose down | |
## docker-new-migrate: create migration files from models (in docker container). | |
docker-new-migrate: | |
docker exec -it \$(BACKEND_CONTAINER) \$(MANAGE) makemigrations | |
## docker-migrate: apply migrations to DB (in docker container). | |
docker-migrate: | |
docker exec -it \$(BACKEND_CONTAINER) \$(MANAGE) migrate | |
## docker-copy-static: copy static files from BACKEND container to NGINX container. | |
docker-copy-static: | |
docker exec -it \$(BACKEND_CONTAINER) \$(MANAGE) collectstatic --noinput | |
docker cp \$(BACKEND_CONTAINER):/tmp/static_content/static /tmp/static | |
docker cp /tmp/static \$(NGINX_CONTAINER):/etc/nginx | |
rm -rf /tmp/static | |
EOF | |
cat <<EOF > Dockerfile | |
FROM python:3.9 AS builder | |
RUN uname -a | |
RUN apt update && apt install -y --no-install-recommends python-dev python-setuptools | |
WORKDIR /srv/project | |
# This prevents Python from writing out pyc files | |
ENV PYTHONDONTWRITEBYTECODE 1 | |
# This keeps Python from buffering stdin/stdout | |
ENV PYTHONUNBUFFERED 1 | |
COPY requirements.txt requirements.txt | |
RUN pip install --upgrade pip | |
RUN pip install -r requirements.txt | |
FROM builder AS builder_app | |
COPY src/ src/ | |
COPY ./Makefile Makefile | |
RUN useradd -ms /bin/bash admin | |
RUN chown -R admin:admin /srv/project | |
RUN chmod 755 /srv/project | |
USER admin | |
#EXPOSE 8000 | |
#CMD ["python", "./src/manage.py", "runserver", "0.0.0.0:8000"] | |
#CMD bash -C "./commands/wsgi_dev.sh" | |
EOF | |
cat <<EOF > docker-compose.yaml | |
version: "3.8" | |
services: | |
nginx: | |
build: ./nginx | |
container_name: nginx | |
ports: | |
- "$NGINX_PORT:$NGINX_CONTAINER_PORT" | |
- "443:443" | |
depends_on: | |
- backend | |
backend: | |
build: . | |
container_name: backend | |
command: make \${RUN_COMMAND} | |
tty: true | |
stdin_open: true | |
restart: always | |
ports: | |
- "$BACKEND_CONTAINER_PORT:$BACKEND_CONTAINER_PORT" | |
- "9000:9000" | |
volumes: | |
- ./:/srv/project | |
# depends_on: | |
# - memcached | |
# - mq | |
# - postgres | |
env_file: .env | |
# celery: | |
# build: . | |
# container_name: celery | |
# command: make celery-run | |
# restart: always | |
# env_file: .env | |
# depends_on: | |
# - mq | |
# volumes: | |
# - ./:/srv/project | |
# | |
# celerybeat: | |
# build: . | |
# container_name: celerybeat | |
# command: make celerybeat-run | |
# restart: always | |
# env_file: .env | |
# depends_on: | |
# - mq | |
# volumes: | |
# - ./:/srv/project | |
# | |
# memcached: | |
# image: memcached:1.6.9 | |
# container_name: memcached | |
# tty: true | |
# stdin_open: true | |
# restart: always | |
# rabbitmq: | |
# image: rabbitmq:3.8-rc-management | |
# container_name: rabbitmq | |
# tty: true | |
# stdin_open: true | |
# restart: always | |
# env_file: .env | |
## ports: | |
## - "15672:15672" | |
# mq: | |
# image: redis:6.2.4 | |
# tty: true | |
# stdin_open: true | |
# restart: always | |
# env_file: .env | |
# | |
# redis-commander: | |
# container_name: redis-commander | |
# hostname: redis-commander | |
# image: rediscommander/redis-commander:latest | |
# restart: always | |
# environment: | |
# - REDIS_HOSTS=redis_container:mq:6379 | |
# ports: | |
# - "8081:8081" | |
# | |
# postgres: | |
# image: postgres:12-alpine | |
# tty: true | |
# stdin_open: true | |
# restart: always | |
# env_file: .env | |
# ports: | |
# - "5432:5432" | |
# volumes: | |
# - db_data:/var/lib/postgresql/data | |
# | |
#volumes: | |
# db_data: | |
EOF | |
mkdir nginx | |
cat <<EOF > nginx/Dockerfile | |
FROM nginx:1.19.0 | |
RUN rm /etc/nginx/conf.d/default.conf | |
COPY nginx.conf /etc/nginx/conf.d | |
COPY proxy_params /etc/nginx/conf.d/proxy_params | |
EOF | |
cat <<EOF > nginx/nginx.conf | |
upstream django { | |
server $BACKEND_CONTAINER_NAME:$BACKEND_CONTAINER_PORT; | |
} | |
server { | |
listen $NGINX_CONTAINER_PORT; | |
listen [::]:$NGINX_CONTAINER_PORT; | |
server_name _; | |
location = /favicon.ico { access_log off; log_not_found off; } | |
location /static/ { | |
root /etc/nginx; | |
} | |
location / { | |
include /etc/nginx/conf.d/proxy_params; | |
proxy_pass http://django; | |
} | |
} | |
EOF | |
cat <<EOF > nginx/proxy_params | |
proxy_redirect off; | |
proxy_set_header Host \$host; | |
proxy_set_header X-Real-IP \$remote_addr; | |
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; | |
client_max_body_size 10m; | |
client_body_buffer_size 128k; | |
proxy_connect_timeout 90; | |
proxy_send_timeout 90; | |
proxy_read_timeout 90; | |
proxy_buffers 32 4k; | |
EOF | |
git_init | |
RUN_MSG="cd $PROJECT_NAME && source ./venv/bin/activate && make run" | |
show_msg "Project successfull created.\nNow run your project\n\n******** RUN IT NOW ********\n\n$RUN_MSG" | |
# just show help (list of available commands). | |
make | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment