mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-08-13 00:14:52 +03:00
A bunch of minor updates
This commit is contained in:
parent
e89f611238
commit
54a9c168fb
|
@ -14,5 +14,5 @@ requirements:
|
|||
- "requirements.txt"
|
||||
- "{{cookiecutter.project_slug}}/requirements/base.txt"
|
||||
- "{{cookiecutter.project_slug}}/requirements/dev.txt"
|
||||
- "{{cookiecutter.project_slug}}/requirements/production.txt"
|
||||
- "{{cookiecutter.project_slug}}/requirements/prod.txt"
|
||||
- "{{cookiecutter.project_slug}}/requirements/test.txt"
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
"author_name": "Your Name",
|
||||
"domain_name": "example.com",
|
||||
"email": "{{ cookiecutter.author_name.lower()|replace(' ', '-') }}@example.com",
|
||||
"version": "0.1.0",
|
||||
"open_source_license": [
|
||||
"MIT",
|
||||
"BSD",
|
||||
|
|
|
@ -18,6 +18,52 @@ HINT = "\x1b[3;33m"
|
|||
SUCCESS = "\x1b[1;32m [SUCCESS]: "
|
||||
|
||||
DEBUG_VALUE = "debug"
|
||||
PROJECT_DIRECTORY = os.path.realpath(os.path.curdir)
|
||||
|
||||
|
||||
def initialize_git(project_directory):
|
||||
"""
|
||||
Initialize the git repo.
|
||||
|
||||
Args:
|
||||
project_directory:
|
||||
"""
|
||||
import subprocess
|
||||
|
||||
print("Initializing git repo...")
|
||||
result = subprocess.run(
|
||||
["git", "init"], cwd=project_directory, encoding="utf8", capture_output=True
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print("Unable to initialize the git repo.")
|
||||
print(result.stdout, result.stderr)
|
||||
|
||||
result = subprocess.run(
|
||||
["git", "add", "."], cwd=project_directory, encoding="utf8", capture_output=True
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print("Unable to add all files into the git repo.")
|
||||
print(result.stdout, result.stderr)
|
||||
|
||||
result = subprocess.run(
|
||||
["git", "commit", '-m"Initial commit"'],
|
||||
cwd=project_directory,
|
||||
encoding="utf8",
|
||||
capture_output=True,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print("Unable to make the initial commit.")
|
||||
print(result.stdout, result.stderr)
|
||||
|
||||
result = subprocess.run(
|
||||
["git", "tag", "0.1.0"],
|
||||
cwd=project_directory,
|
||||
encoding="utf8",
|
||||
capture_output=True,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print("Unable to tag the initial commit.")
|
||||
print(result.stdout, result.stderr)
|
||||
|
||||
|
||||
def remove_open_source_files():
|
||||
|
@ -32,20 +78,10 @@ def remove_gplv3_files():
|
|||
os.remove(file_name)
|
||||
|
||||
|
||||
def remove_pycharm_files():
|
||||
idea_dir_path = ".idea"
|
||||
if os.path.exists(idea_dir_path):
|
||||
shutil.rmtree(idea_dir_path)
|
||||
|
||||
docs_dir_path = os.path.join("docs", "pycharm")
|
||||
if os.path.exists(docs_dir_path):
|
||||
shutil.rmtree(docs_dir_path)
|
||||
|
||||
|
||||
def remove_docker_files():
|
||||
shutil.rmtree("compose")
|
||||
|
||||
file_names = ["dev.yml", ".dockerignore"]
|
||||
file_names = ["local.yml", ".dockerignore"]
|
||||
for file_name in file_names:
|
||||
os.remove(file_name)
|
||||
|
||||
|
@ -146,20 +182,8 @@ def set_django_secret_key(file_path):
|
|||
return django_secret_key
|
||||
|
||||
|
||||
def set_django_admin_url(file_path):
|
||||
django_admin_url = set_flag(
|
||||
file_path,
|
||||
"!!!SET DJANGO_ADMIN_URL!!!",
|
||||
formatted="{}/",
|
||||
length=32,
|
||||
using_digits=True,
|
||||
using_ascii_letters=True,
|
||||
)
|
||||
return django_admin_url
|
||||
|
||||
|
||||
def generate_random_user():
|
||||
return generate_random_string(length=32, using_ascii_letters=True)
|
||||
return generate_random_string(length=10, using_ascii_letters=True)
|
||||
|
||||
|
||||
def generate_postgres_user(debug=False):
|
||||
|
@ -209,36 +233,23 @@ def append_to_gitignore_file(s):
|
|||
|
||||
|
||||
def set_flags_in_envs(postgres_user, celery_flower_user, debug=False):
|
||||
local_django_envs_path = os.path.join(".envs", "dev", "django")
|
||||
production_django_envs_path = os.path.join(".envs", "prod", "django")
|
||||
local_postgres_envs_path = os.path.join(".envs", "dev", "postgres")
|
||||
|
||||
dev_postgres_env_path = os.path.join(".envs", "dev", "postgres")
|
||||
pg_pass = set_postgres_password(dev_postgres_env_path)
|
||||
set_flag(production_django_envs_path, "!!!SET POSTGRES_PASSWORD!!!", value=pg_pass)
|
||||
set_django_secret_key(production_django_envs_path)
|
||||
set_django_admin_url(production_django_envs_path)
|
||||
|
||||
set_postgres_user(local_postgres_envs_path, value=postgres_user)
|
||||
set_postgres_password(
|
||||
local_postgres_envs_path, value=DEBUG_VALUE if debug else None
|
||||
)
|
||||
|
||||
set_celery_flower_user(local_django_envs_path, value=celery_flower_user)
|
||||
set_celery_flower_password(
|
||||
local_django_envs_path, value=DEBUG_VALUE if debug else None
|
||||
)
|
||||
set_celery_flower_user(production_django_envs_path, value=celery_flower_user)
|
||||
set_celery_flower_password(
|
||||
production_django_envs_path, value=DEBUG_VALUE if debug else None
|
||||
)
|
||||
set_celery_flower_password(production_django_envs_path)
|
||||
|
||||
|
||||
def set_flags_in_settings_files():
|
||||
set_django_secret_key(
|
||||
os.path.join("{{ cookiecutter.project_slug }}", "settings", "dev_template.py")
|
||||
)
|
||||
set_django_secret_key(
|
||||
os.path.join("{{ cookiecutter.project_slug }}", "settings", "test.py")
|
||||
)
|
||||
|
||||
def remove_storage():
|
||||
os.remove(os.path.join("{{ cookiecutter.project_slug }}", "storage.py"))
|
||||
|
||||
|
||||
def remove_envs_and_associated_files():
|
||||
shutil.rmtree(".envs")
|
||||
|
@ -250,6 +261,12 @@ def create_dev_settings():
|
|||
os.path.join("{{ cookiecutter.project_slug }}", "settings", "dev_template.py"),
|
||||
os.path.join("{{ cookiecutter.project_slug }}", "settings", "dev.py"),
|
||||
)
|
||||
shutil.copy(os.path.join(".envs", "prod", "django"), ".env")
|
||||
set_flag(
|
||||
".env",
|
||||
"DJANGO_SETTINGS_MODULE=test_project.settings.prod",
|
||||
value="DJANGO_SETTINGS_MODULE=test_project.settings",
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
|
@ -263,14 +280,14 @@ def main():
|
|||
if "{{ cookiecutter.open_source_license}}" != "GPLv3":
|
||||
remove_gplv3_files()
|
||||
|
||||
append_to_gitignore_file(".env")
|
||||
append_to_gitignore_file(".envs/*")
|
||||
|
||||
if "{{ cookiecutter.cloud_provider}}".lower() == "none":
|
||||
print(
|
||||
WARNING + "You chose not to use a cloud provider, "
|
||||
"media files won't be served in production." + TERMINATOR
|
||||
)
|
||||
remove_storage()
|
||||
elif "{{ cookiecutter.cloud_provider}}".lower() == "GCP":
|
||||
remove_storage()
|
||||
|
||||
if "{{ cookiecutter.use_celery }}".lower() == "n":
|
||||
remove_celery_files()
|
||||
|
@ -278,6 +295,8 @@ def main():
|
|||
if "{{ cookiecutter.use_travisci }}".lower() == "n":
|
||||
remove_dottravisyml_file()
|
||||
|
||||
initialize_git(PROJECT_DIRECTORY)
|
||||
|
||||
print(SUCCESS + "Project initialized, keep up the good work!" + TERMINATOR)
|
||||
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
# General
|
||||
# ------------------------------------------------------------------------------
|
||||
USE_DOCKER=yes
|
||||
IPYTHONDIR=/app/.ipython
|
||||
|
||||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
# Redis
|
||||
# ------------------------------------------------------------------------------
|
||||
REDIS_URL=redis://redis:6379/0
|
||||
|
||||
# Celery
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Flower
|
||||
CELERY_FLOWER_USER=!!!SET CELERY_FLOWER_USER!!!
|
||||
CELERY_FLOWER_PASSWORD=!!!SET CELERY_FLOWER_PASSWORD!!!
|
||||
{% endif %}
|
|
@ -1,7 +1,6 @@
|
|||
# PostgreSQL
|
||||
# ------------------------------------------------------------------------------
|
||||
POSTGRES_HOST=postgres
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_DB={{ cookiecutter.project_slug }}
|
||||
POSTGRES_USER=!!!SET POSTGRES_USER!!!
|
||||
POSTGRES_PASSWORD=!!!SET POSTGRES_PASSWORD!!!
|
||||
# PGDATA=/var/lib/postgresql/data
|
||||
# POSTGRES_INITDB_WALDIR=
|
||||
# POSTGRES_INITDB_ARGS=
|
||||
# POSTGRES_USER=postgres
|
||||
# POSTGRES_DB=postgres
|
||||
|
|
|
@ -1,32 +1,47 @@
|
|||
# General
|
||||
# ------------------------------------------------------------------------------
|
||||
# DJANGO_READ_DOT_ENV_FILE=True
|
||||
DJANGO_SETTINGS_MODULE=config.settings.production
|
||||
DJANGO_SETTINGS_MODULE={{ cookiecutter.project_slug }}.settings.prod
|
||||
DJANGO_SECRET_KEY=!!!SET DJANGO_SECRET_KEY!!!
|
||||
DJANGO_ADMIN_URL=!!!SET DJANGO_ADMIN_URL!!!
|
||||
DJANGO_ADMIN_URL=admin/
|
||||
DJANGO_ALLOWED_HOSTS=.{{ cookiecutter.domain_name }}
|
||||
DJANGO_DEBUG=False
|
||||
|
||||
DATABASE_URL=postgres://postgres:!!!SET POSTGRES_PASSWORD!!!@localhost/{{ cookiecutter.project_slug }}
|
||||
|
||||
# Security
|
||||
# ------------------------------------------------------------------------------
|
||||
# TIP: better off using DNS, however, redirect is OK too
|
||||
DJANGO_SECURE_SSL_REDIRECT=False
|
||||
DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS=True
|
||||
DJANGO_SECURE_HSTS_PRELOAD=True
|
||||
DJANGO_SECURE_CONTENT_TYPE_NOSNIFF=True
|
||||
|
||||
# Email
|
||||
# ------------------------------------------------------------------------------
|
||||
MAILGUN_API_KEY=
|
||||
DJANGO_SERVER_EMAIL=
|
||||
MAILGUN_DOMAIN=
|
||||
DJANGO_EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
|
||||
EMAIL_HOST=localhost
|
||||
EMAIL_HOST_USER=
|
||||
EMAIL_HOST_PASSWORD=
|
||||
EMAIL_PORT=25
|
||||
DJANGO_EMAIL_SUBJECT_PREFIX="[{{cookiecutter.project_name}}]"
|
||||
|
||||
{% if cookiecutter.cloud_provider == 'AWS' %}
|
||||
# AWS
|
||||
# ------------------------------------------------------------------------------
|
||||
DJANGO_AWS_ACCESS_KEY_ID=
|
||||
DJANGO_AWS_SECRET_ACCESS_KEY=
|
||||
DJANGO_AWS_STORAGE_BUCKET_NAME=
|
||||
DJANGO_AWS_S3_REGION_NAME=
|
||||
{% elif cookiecutter.cloud_provider == 'GCP' %}
|
||||
# GCP
|
||||
# ------------------------------------------------------------------------------
|
||||
GOOGLE_APPLICATION_CREDENTIALS=
|
||||
DJANGO_GCP_STORAGE_BUCKET_NAME=
|
||||
{% elif cookiecutter.cloud_provider == 'Azure' %}
|
||||
DJANGO_AZURE_ACCOUNT_NAME=
|
||||
DJANGO_AZURE_ACCOUNT_KEY=
|
||||
DJANGO_AZURE_CONTAINER=
|
||||
{% endif %}
|
||||
# django-allauth
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -43,15 +58,16 @@ WEB_CONCURRENCY=4
|
|||
# Sentry
|
||||
# ------------------------------------------------------------------------------
|
||||
SENTRY_DSN=
|
||||
# SENTRY_LOG_LEVEL=
|
||||
{% endif %}
|
||||
|
||||
# Redis
|
||||
# ------------------------------------------------------------------------------
|
||||
REDIS_URL=redis://redis:6379/0
|
||||
REDIS_URL=redis://localhost:6379/0
|
||||
{% if cookiecutter.use_celery == 'y' %}
|
||||
# Celery
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
CELERY_BROKER_URL=redis://localhost:6379/0
|
||||
# Flower
|
||||
CELERY_FLOWER_USER=!!!SET CELERY_FLOWER_USER!!!
|
||||
CELERY_FLOWER_PASSWORD=!!!SET CELERY_FLOWER_PASSWORD!!!
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
||||
<option name="SCRIPT_NAME" value="merge_production_dotenvs_in_dotenv.py" />
|
||||
<option name="SCRIPT_NAME" value="./bin/merge_production_dotenvs_in_dotenv.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.local" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="{{ cookiecutter.project_slug }}.settings" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.local" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="{{ cookiecutter.project_slug }}.settings" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.local" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="{{ cookiecutter.project_slug }}.settings" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
|
|
|
@ -25,41 +25,15 @@ RUN addgroup -S django \
|
|||
|
||||
# Requirements are installed here to ensure they will be cached.
|
||||
COPY ./requirements /requirements
|
||||
RUN pip install --no-cache-dir -r /requirements/production.txt \
|
||||
RUN pip install --no-cache-dir -r /requirements/prod.txt \
|
||||
&& rm -rf /requirements
|
||||
|
||||
COPY ./compose/production/django/entrypoint /entrypoint
|
||||
RUN sed -i 's/\r$//g' /entrypoint
|
||||
RUN chmod +x /entrypoint
|
||||
RUN chown django /entrypoint
|
||||
|
||||
COPY ./compose/production/django/start /start
|
||||
RUN sed -i 's/\r$//g' /start
|
||||
RUN chmod +x /start
|
||||
RUN chown django /start
|
||||
|
||||
{%- if cookiecutter.use_celery == "y" %}
|
||||
COPY ./compose/production/django/celery/worker/start /start-celeryworker
|
||||
RUN sed -i 's/\r$//g' /start-celeryworker
|
||||
RUN chmod +x /start-celeryworker
|
||||
RUN chown django /start-celeryworker
|
||||
|
||||
COPY ./compose/production/django/celery/beat/start /start-celerybeat
|
||||
RUN sed -i 's/\r$//g' /start-celerybeat
|
||||
RUN chmod +x /start-celerybeat
|
||||
RUN chown django /start-celerybeat
|
||||
|
||||
COPY ./compose/production/django/celery/flower/start /start-flower
|
||||
RUN sed -i 's/\r$//g' /start-flower
|
||||
RUN chmod +x /start-flower
|
||||
{%- endif %}
|
||||
|
||||
COPY --from=client-builder /app /app
|
||||
|
||||
RUN chown -R django /app
|
||||
|
||||
RUN chmod +x /app/bin/*
|
||||
USER django
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["/entrypoint"]
|
||||
ENTRYPOINT ["/app/bin/entrypoint"]
|
||||
|
|
|
@ -79,7 +79,7 @@ To run a celery worker:
|
|||
.. code-block:: bash
|
||||
|
||||
cd {{cookiecutter.project_slug}}
|
||||
celery -A config.celery_app worker -l info
|
||||
celery -A {{ cookiecutter.project_slug }}.celery_app worker -l info
|
||||
|
||||
Please note: For Celery's import magic to work, it is important *where* the celery commands are run. If you are in the same folder with *manage.py*, you should be right.
|
||||
|
||||
|
|
19
{{cookiecutter.project_slug}}/bin/entrypoint
Normal file → Executable file
19
{{cookiecutter.project_slug}}/bin/entrypoint
Normal file → Executable file
|
@ -10,12 +10,13 @@ set -o nounset
|
|||
export CELERY_BROKER_URL="${REDIS_URL}"
|
||||
{% endif %}
|
||||
|
||||
if [ -z "${POSTGRES_USER}" ]; then
|
||||
base_postgres_image_default_user='postgres'
|
||||
export POSTGRES_USER="${base_postgres_image_default_user}"
|
||||
if [ -z "${DATABASE_URL}" ]; then
|
||||
if [ -z "${POSTGRES_USER}" ]; then
|
||||
base_postgres_image_default_user='postgres'
|
||||
export POSTGRES_USER="${base_postgres_image_default_user}"
|
||||
fi
|
||||
export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}"
|
||||
fi
|
||||
export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}"
|
||||
|
||||
postgres_ready() {
|
||||
python << END
|
||||
import sys
|
||||
|
@ -23,13 +24,7 @@ import sys
|
|||
import psycopg2
|
||||
|
||||
try:
|
||||
psycopg2.connect(
|
||||
dbname="${POSTGRES_DB}",
|
||||
user="${POSTGRES_USER}",
|
||||
password="${POSTGRES_PASSWORD}",
|
||||
host="${POSTGRES_HOST}",
|
||||
port="${POSTGRES_PORT}",
|
||||
)
|
||||
psycopg2.connect("${DATABASE_URL}")
|
||||
except psycopg2.OperationalError:
|
||||
sys.exit(-1)
|
||||
sys.exit(0)
|
||||
|
|
0
{{cookiecutter.project_slug}}/bin/merge_production_dotenvs_in_dotenv.py
Normal file → Executable file
0
{{cookiecutter.project_slug}}/bin/merge_production_dotenvs_in_dotenv.py
Normal file → Executable file
11
{{cookiecutter.project_slug}}/bin/setup-dev-env
Executable file
11
{{cookiecutter.project_slug}}/bin/setup-dev-env
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
PROJECT_PATH=`pwd`
|
||||
ENV_PATH="${PROJECT_PATH}/.envs/prod/django"
|
||||
SETTINGS_PATH="${PROJECT_PATH}/{{ cookiecutter.project_slug }}/settings/dev_template.py"
|
||||
|
||||
echo "Creating local .env file"
|
||||
cp ${ENV_PATH} "${PROJECT_PATH}/.env"
|
||||
|
||||
echo "Creating local dev.py settings"
|
||||
cp ${SETTINGS_PATH} "${PROJECT_PATH}/{{ cookiecutter.project_slug }}/settings/dev.py"
|
2
{{cookiecutter.project_slug}}/bin/start-celery-beat
Normal file → Executable file
2
{{cookiecutter.project_slug}}/bin/start-celery-beat
Normal file → Executable file
|
@ -5,4 +5,4 @@ set -o pipefail
|
|||
set -o nounset
|
||||
|
||||
|
||||
celery -A config.celery_app beat -l INFO
|
||||
celery -A {{ cookiecutter.project_slug }}.celery_app beat -l INFO
|
||||
|
|
2
{{cookiecutter.project_slug}}/bin/start-celery-worker
Normal file → Executable file
2
{{cookiecutter.project_slug}}/bin/start-celery-worker
Normal file → Executable file
|
@ -5,4 +5,4 @@ set -o pipefail
|
|||
set -o nounset
|
||||
|
||||
|
||||
celery -A config.celery_app worker -l INFO
|
||||
celery -A {{ cookiecutter.project_slug }}.celery_app worker -l INFO
|
||||
|
|
2
{{cookiecutter.project_slug}}/bin/start-django
Normal file → Executable file
2
{{cookiecutter.project_slug}}/bin/start-django
Normal file → Executable file
|
@ -6,4 +6,4 @@ set -o nounset
|
|||
|
||||
|
||||
python /app/manage.py collectstatic --noinput
|
||||
/usr/local/bin/gunicorn config.wsgi --bind 0.0.0.0:8000 --chdir=/app
|
||||
/usr/local/bin/gunicorn {{ cookiecutter.project_slug }}.wsgi --bind 0.0.0.0:8000 --chdir=/app
|
||||
|
|
0
{{cookiecutter.project_slug}}/bin/start-django-dev
Normal file → Executable file
0
{{cookiecutter.project_slug}}/bin/start-django-dev
Normal file → Executable file
2
{{cookiecutter.project_slug}}/bin/start-flower
Normal file → Executable file
2
{{cookiecutter.project_slug}}/bin/start-flower
Normal file → Executable file
|
@ -5,6 +5,6 @@ set -o nounset
|
|||
|
||||
|
||||
celery flower \
|
||||
--app=config.celery_app \
|
||||
--app={{ cookiecutter.project_slug }}.celery_app \
|
||||
--broker="${CELERY_BROKER_URL}" \
|
||||
--basic_auth="${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}"
|
||||
|
|
|
@ -8,8 +8,8 @@ services:
|
|||
django:{% if cookiecutter.use_celery == 'y' %} &django{% endif %}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./compose/dev/django/Dockerfile
|
||||
image: {{ cookiecutter.project_slug }}_local_django
|
||||
dockerfile: ./Dockerfile
|
||||
image: {{ cookiecutter.project_slug }}_django
|
||||
depends_on:
|
||||
- postgres
|
||||
{%- if cookiecutter.use_mailhog == 'y' %}
|
||||
|
@ -18,22 +18,20 @@ services:
|
|||
volumes:
|
||||
- .:/app
|
||||
env_file:
|
||||
- ./.envs/dev/django
|
||||
- ./.envs/dev/postgres
|
||||
- .env
|
||||
ports:
|
||||
- "8000:8000"
|
||||
command: /start
|
||||
command: /app/bin/start-django-dev
|
||||
|
||||
postgres:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: postgres:11-alpine
|
||||
image: {{ cookiecutter.project_slug }}_postgres
|
||||
image: postgres:11-alpine
|
||||
volumes:
|
||||
- local_postgres_data:/var/lib/postgresql/data
|
||||
- local_postgres_data_backups:/backups
|
||||
env_file:
|
||||
- .envs/dev/postgres
|
||||
- .env
|
||||
ports:
|
||||
- "5432:5432"
|
||||
{%- if cookiecutter.use_mailhog == 'y' %}
|
||||
|
||||
mailhog:
|
||||
|
@ -56,7 +54,7 @@ services:
|
|||
- mailhog
|
||||
{%- endif %}
|
||||
ports: []
|
||||
command: /start-celeryworker
|
||||
command: /app/bin/start-celeryworker
|
||||
|
||||
celerybeat:
|
||||
<<: *django
|
||||
|
@ -68,22 +66,19 @@ services:
|
|||
- mailhog
|
||||
{%- endif %}
|
||||
ports: []
|
||||
command: /start-celerybeat
|
||||
command: /app/bin/start-celerybeat
|
||||
|
||||
flower:
|
||||
<<: *django
|
||||
image: {{ cookiecutter.project_slug }}_flower
|
||||
ports:
|
||||
- "5555:5555"
|
||||
command: /start-flower
|
||||
command: /app/bin/start-flower
|
||||
|
||||
{%- endif %}
|
||||
|
||||
node:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: node:10-stretch-slim
|
||||
image: {{ cookiecutter.project_slug }}_node
|
||||
image: node:10-stretch-slim
|
||||
depends_on:
|
||||
- django
|
||||
volumes:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "{{cookiecutter.project_slug}}",
|
||||
"version": "{{ cookiecutter.version }}",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^9.4.7",
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[pytest]
|
||||
addopts = --ds=config.settings.test
|
||||
addopts = --ds={{ cookiecutter.project_slug }}.settings.test
|
||||
norecursedirs = node_modules
|
||||
|
|
|
@ -29,3 +29,10 @@ django-redis==4.10.0 # https://github.com/niwinz/django-redis
|
|||
# Django REST Framework
|
||||
djangorestframework==3.10.0 # https://github.com/encode/django-rest-framework
|
||||
coreapi==2.3.3 # https://github.com/core-api/python-client
|
||||
{%- if cookiecutter.cloud_provider == 'AWS' %}
|
||||
django-storages[boto3]==1.7.1 # https://github.com/jschneier/django-storages
|
||||
{%- elif cookiecutter.cloud_provider == 'GCP' %}
|
||||
django-storages[google]==1.7.1 # https://github.com/jschneier/django-storages
|
||||
{%- elif cookiecutter.cloud_provider == 'Azure' %}
|
||||
django-storages[azure]==1.7.1 # https://github.com/jschneier/django-storages
|
||||
{%- endif %}
|
||||
|
|
9
{{cookiecutter.project_slug}}/requirements/prod.txt
Normal file
9
{{cookiecutter.project_slug}}/requirements/prod.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
# PRECAUTION: avoid production dependencies that aren't in development
|
||||
|
||||
-r ./base.txt
|
||||
|
||||
gunicorn==19.9.0 # https://github.com/benoitc/gunicorn
|
||||
psycopg2==2.8.3 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
|
||||
{%- if cookiecutter.use_sentry == "y" %}
|
||||
sentry-sdk==0.10.2 # https://github.com/getsentry/sentry-python
|
||||
{%- endif %}
|
|
@ -1,20 +0,0 @@
|
|||
# PRECAUTION: avoid production dependencies that aren't in development
|
||||
|
||||
-r ./base.txt
|
||||
|
||||
gunicorn==19.9.0 # https://github.com/benoitc/gunicorn
|
||||
psycopg2==2.8.3 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
|
||||
{%- if cookiecutter.use_sentry == "y" %}
|
||||
sentry-sdk==0.10.2 # https://github.com/getsentry/sentry-python
|
||||
{%- endif %}
|
||||
|
||||
# Django
|
||||
# ------------------------------------------------------------------------------
|
||||
{%- if cookiecutter.cloud_provider == 'AWS' %}
|
||||
django-storages[boto3]==1.7.1 # https://github.com/jschneier/django-storages
|
||||
{%- elif cookiecutter.cloud_provider == 'GCP' %}
|
||||
django-storages[google]==1.7.1 # https://github.com/jschneier/django-storages
|
||||
{%- elif cookiecutter.cloud_provider == 'Azure' %}
|
||||
django-storages[azure]==1.7.1 # https://github.com/jschneier/django-storages
|
||||
{%- endif %}
|
||||
django-anymail[mailgun]==6.1.0 # https://github.com/anymail/django-anymail
|
|
@ -1,4 +1,4 @@
|
|||
__version__ = "{{ cookiecutter.version }}"
|
||||
__version__ = ""
|
||||
__version_info__ = tuple(
|
||||
[
|
||||
int(num) if num.isdigit() else num
|
||||
|
|
|
@ -1,21 +1,6 @@
|
|||
"""
|
||||
Base settings to build other settings files upon.
|
||||
"""
|
||||
{% if cookiecutter.use_sentry == 'y' -%}
|
||||
import logging
|
||||
|
||||
import sentry_sdk
|
||||
|
||||
from sentry_sdk.integrations.django import DjangoIntegration
|
||||
from sentry_sdk.integrations.logging import LoggingIntegration
|
||||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
from sentry_sdk.integrations.celery import CeleryIntegration
|
||||
{% endif %}{% endif -%}
|
||||
{% if cookiecutter.cloud_provider == 'AWS' %}
|
||||
from storages.backends.s3boto3 import S3Boto3Storage
|
||||
{% elif cookiecutter.cloud_provider == 'Azure' %}
|
||||
from storages.backends.azure_storage import AzureStorage
|
||||
{%- endif %}
|
||||
import environ
|
||||
|
||||
ROOT_DIR = (
|
||||
|
@ -32,7 +17,7 @@ env.read_env(str(ROOT_DIR.path(".env")))
|
|||
# ------------------------------------------------------------------------------
|
||||
DEBUG = env.bool("DJANGO_DEBUG", False)
|
||||
SITE_ID = 1
|
||||
ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["{{ cookiecutter.domain_name }}"])
|
||||
ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=[".{{ cookiecutter.domain_name }}"])
|
||||
|
||||
|
||||
# DATABASES
|
||||
|
@ -234,28 +219,13 @@ STATICFILES_FINDERS = [
|
|||
{%- endif %}
|
||||
]
|
||||
{%- if cookiecutter.cloud_provider == 'AWS' %}
|
||||
|
||||
|
||||
class StaticRootS3Boto3Storage(S3Boto3Storage):
|
||||
location = "static"
|
||||
default_acl = "public-read"
|
||||
|
||||
|
||||
STATICFILES_STORAGE = "settings.base.StaticRootS3Boto3Storage"
|
||||
STATICFILES_STORAGE = "{{ cookiecutter.project_slug }}.storage.StaticRootS3Boto3Storage"
|
||||
STATIC_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/static/"
|
||||
{% elif cookiecutter.cloud_provider == 'GCP' %}
|
||||
STATICFILES_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
|
||||
STATIC_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/"
|
||||
{% elif cookiecutter.cloud_provider == 'Azure' %}
|
||||
|
||||
|
||||
class PublicAzureStorage(AzureStorage):
|
||||
account_name = AZURE_ACCOUNT_NAME
|
||||
account_key = AZURE_ACCOUNT_KEY
|
||||
azure_container = AZURE_CONTAINER
|
||||
expiration_secs = None
|
||||
|
||||
STATICFILES_STORAGE = "settings.base.PublicAzureStorage"
|
||||
STATICFILES_STORAGE = "{{ cookiecutter.project_slug }}.storage.PublicAzureStorage"
|
||||
{% elif cookiecutter.use_whitenoise == 'y' %}
|
||||
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
|
||||
{% else %}
|
||||
|
@ -273,14 +243,7 @@ COMPRESS_URL = STATIC_URL
|
|||
# https://docs.djangoproject.com/en/2.2/ref/settings/#file-uploads
|
||||
# ------------------------------------------------------------------------------
|
||||
{%- if cookiecutter.cloud_provider == 'AWS' %}
|
||||
|
||||
|
||||
class MediaRootS3Boto3Storage(S3Boto3Storage):
|
||||
location = "media"
|
||||
file_overwrite = False
|
||||
|
||||
|
||||
DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootS3Boto3Storage"
|
||||
DEFAULT_FILE_STORAGE = "{{ cookiecutter.project_slug }}.storage.MediaRootS3Boto3Storage"
|
||||
MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/"
|
||||
{% elif cookiecutter.cloud_provider == 'GCP' %}
|
||||
DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
|
||||
|
@ -384,34 +347,8 @@ LOGGING = {
|
|||
"handlers": ["console"],
|
||||
"propagate": False,
|
||||
},
|
||||
{%- if cookiecutter.use_sentry == 'y' %}
|
||||
"sentry_sdk": { # Errors logged by Sentry's SDK itself
|
||||
"level": "ERROR",
|
||||
"handlers": ["console"],
|
||||
"propagate": False,
|
||||
},
|
||||
{%- endif %}
|
||||
},
|
||||
}
|
||||
|
||||
{%- if cookiecutter.use_sentry == 'y' %}
|
||||
# Sentry
|
||||
# ------------------------------------------------------------------------------
|
||||
SENTRY_DSN = env("SENTRY_DSN")
|
||||
SENTRY_LOG_LEVEL = env.int("DJANGO_SENTRY_LOG_LEVEL", logging.INFO)
|
||||
|
||||
sentry_logging = LoggingIntegration(
|
||||
level=SENTRY_LOG_LEVEL, # Capture info and above as breadcrumbs
|
||||
event_level=logging.ERROR, # Send errors as events
|
||||
)
|
||||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
sentry_sdk.init(
|
||||
dsn=SENTRY_DSN,
|
||||
integrations=[sentry_logging, DjangoIntegration(), CeleryIntegration()],
|
||||
)
|
||||
{%- else %}
|
||||
sentry_sdk.init(dsn=SENTRY_DSN, integrations=[sentry_logging, DjangoIntegration()])
|
||||
{% endif -%}{%- endif %}
|
||||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
|
||||
|
||||
|
|
|
@ -3,19 +3,11 @@ from .base import env
|
|||
|
||||
# GENERAL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
||||
DEBUG = True
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||
SECRET_KEY = env(
|
||||
"DJANGO_SECRET_KEY",
|
||||
default="!!!SET DJANGO_SECRET_KEY!!!",
|
||||
)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1"]
|
||||
|
||||
# CACHES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#caches
|
||||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
from .base import * # noqa
|
||||
from .base import env # noqa
|
||||
{% if cookiecutter.use_sentry == 'y' -%}
|
||||
import logging
|
||||
|
||||
import sentry_sdk
|
||||
|
||||
from sentry_sdk.integrations.django import DjangoIntegration
|
||||
from sentry_sdk.integrations.logging import LoggingIntegration
|
||||
{% if cookiecutter.use_celery == 'y' -%}
|
||||
from sentry_sdk.integrations.celery import CeleryIntegration
|
||||
{% endif %}{% endif %}
|
||||
|
||||
DEBUG = False # Forcible override to turn DEBUG off in production
|
||||
|
||||
# TEMPLATES
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
|
||||
|
@ -13,3 +25,66 @@ TEMPLATES[0]["OPTIONS"]["loaders"] = [ # noqa F405
|
|||
],
|
||||
)
|
||||
]
|
||||
|
||||
# LOGGING
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#logging
|
||||
# ------------------------------------------------------------------------------
|
||||
# See https://docs.djangoproject.com/en/dev/topics/logging for
|
||||
# more details on how to customize your logging configuration.
|
||||
LOGGING = {
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"formatters": {
|
||||
"verbose": {
|
||||
"format": "%(levelname)s %(asctime)s %(module)s "
|
||||
"%(process)d %(thread)d %(message)s"
|
||||
}
|
||||
},
|
||||
"handlers": {
|
||||
"console": {
|
||||
"level": "DEBUG",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "verbose",
|
||||
}
|
||||
},
|
||||
"root": {"level": "INFO", "handlers": ["console"]},
|
||||
"loggers": {
|
||||
"django.db.backends": {
|
||||
"level": "ERROR",
|
||||
"handlers": ["console"],
|
||||
"propagate": False,
|
||||
},
|
||||
"django.security.DisallowedHost": {
|
||||
"level": "ERROR",
|
||||
"handlers": ["console"],
|
||||
"propagate": False,
|
||||
},
|
||||
{%- if cookiecutter.use_sentry == 'y' %}
|
||||
"sentry_sdk": { # Errors logged by Sentry's SDK itself
|
||||
"level": "ERROR",
|
||||
"handlers": ["console"],
|
||||
"propagate": False,
|
||||
},
|
||||
{%- endif %}
|
||||
},
|
||||
}
|
||||
|
||||
{%- if cookiecutter.use_sentry == 'y' %}
|
||||
# Sentry
|
||||
# ------------------------------------------------------------------------------
|
||||
SENTRY_DSN = env("SENTRY_DSN")
|
||||
SENTRY_LOG_LEVEL = env.int("DJANGO_SENTRY_LOG_LEVEL", logging.INFO)
|
||||
|
||||
sentry_logging = LoggingIntegration(
|
||||
level=SENTRY_LOG_LEVEL, # Capture info and above as breadcrumbs
|
||||
event_level=logging.ERROR, # Send errors as events
|
||||
)
|
||||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
sentry_sdk.init(
|
||||
dsn=SENTRY_DSN,
|
||||
integrations=[sentry_logging, DjangoIntegration(), CeleryIntegration()],
|
||||
)
|
||||
{%- else %}
|
||||
sentry_sdk.init(dsn=SENTRY_DSN, integrations=[sentry_logging, DjangoIntegration()])
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
|
|
|
@ -7,19 +7,15 @@ from .base import env
|
|||
|
||||
# GENERAL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
||||
DEBUG = False
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||
SECRET_KEY = env(
|
||||
"DJANGO_SECRET_KEY",
|
||||
default="!!!SET DJANGO_SECRET_KEY!!!",
|
||||
)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#test-runner
|
||||
TEST_RUNNER = "django.test.runner.DiscoverRunner"
|
||||
|
||||
# CACHES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#caches
|
||||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
||||
|
@ -29,7 +25,6 @@ CACHES = {
|
|||
|
||||
# PASSWORDS
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers
|
||||
PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"]
|
||||
|
||||
# TEMPLATES
|
||||
|
@ -46,7 +41,6 @@ TEMPLATES[0]["OPTIONS"]["loaders"] = [ # noqa F405
|
|||
|
||||
# EMAIL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
|
||||
EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
|
||||
|
||||
# Your stuff...
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
{%- if cookiecutter.cloud_provider == 'AWS' -%}
|
||||
from storages.backends.s3boto3 import S3Boto3Storage
|
||||
|
||||
|
||||
class StaticRootS3Boto3Storage(S3Boto3Storage):
|
||||
location = "static"
|
||||
default_acl = "public-read"
|
||||
|
||||
|
||||
class MediaRootS3Boto3Storage(S3Boto3Storage):
|
||||
location = "media"
|
||||
file_overwrite = False
|
||||
{%- elif cookiecutter.cloud_provider == 'Azure' %}
|
||||
from storages.backends.azure_storage import AzureStorage
|
||||
|
||||
|
||||
class PublicAzureStorage(AzureStorage):
|
||||
expiration_secs = None
|
||||
{%- endif %}
|
|
@ -27,8 +27,8 @@ sys.path.append(os.path.join(app_path, "{{ cookiecutter.project_slug }}"))
|
|||
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
|
||||
# if running multiple sites in the same mod_wsgi process. To fix this, use
|
||||
# mod_wsgi daemon mode with each site in its own daemon process, or use
|
||||
# os.environ["DJANGO_SETTINGS_MODULE"] = "config.settings.production"
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
|
||||
# os.environ["DJANGO_SETTINGS_MODULE"] = "{{ cookiecutter.project_slug }}.settings.prod"
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ cookiecutter.project_slug }}.settings.prod")
|
||||
|
||||
# This application object is used by any WSGI server configured to use this
|
||||
# file. This includes Django's development server, if the WSGI_APPLICATION
|
||||
|
|
Loading…
Reference in New Issue
Block a user