add superuser creation command and update settings for environment variables
This commit is contained in:
9
.env.example
Normal file
9
.env.example
Normal file
@@ -0,0 +1,9 @@
|
||||
# Django settings
|
||||
DJANGO_SUPERUSER_USERNAME=admin
|
||||
DJANGO_SUPERUSER_EMAIL=admin@example.com
|
||||
DJANGO_SUPERUSER_PASSWORD=adminpassword
|
||||
DEBUG=False
|
||||
|
||||
SECRET_KEY=your-secret-key
|
||||
ALLOWED_HOSTS=localhost,127.0.0.1
|
||||
CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -33,3 +33,5 @@ build/
|
||||
*.log
|
||||
*.tmp
|
||||
*.swp
|
||||
|
||||
.env
|
18
Dockerfile
Normal file
18
Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
||||
FROM python:3.13-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
||||
COPY requirements.txt /app/
|
||||
|
||||
# Install dependencies
|
||||
RUN pip install --upgrade pip \
|
||||
&& pip install -r requirements.txt \
|
||||
&& pip install gunicorn
|
||||
|
||||
# Copy the rest of the project
|
||||
COPY . /app/
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
|
0
api/management/__init__.py
Normal file
0
api/management/__init__.py
Normal file
0
api/management/commands/__init__.py
Normal file
0
api/management/commands/__init__.py
Normal file
18
api/management/commands/createsuperuser_if_not_exists.py
Normal file
18
api/management/commands/createsuperuser_if_not_exists.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.contrib.auth import get_user_model
|
||||
import os
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Create a superuser if it doesn't already exist"
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
User = get_user_model()
|
||||
username = os.getenv("DJANGO_SUPERUSER_USERNAME")
|
||||
email = os.getenv("DJANGO_SUPERUSER_EMAIL")
|
||||
password = os.getenv("DJANGO_SUPERUSER_PASSWORD")
|
||||
|
||||
if not User.objects.filter(username=username).exists():
|
||||
User.objects.create_superuser(username=username, email=email, password=password)
|
||||
self.stdout.write(self.style.SUCCESS(f"Superuser {username} created"))
|
||||
else:
|
||||
self.stdout.write(self.style.WARNING(f"Superuser {username} already exists"))
|
19
docker-compose.yml
Normal file
19
docker-compose.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
command: >
|
||||
sh -c "python manage.py migrate &&
|
||||
python manage.py createsuperuser_if_not_exists &&
|
||||
python manage.py collectstatic --noinput &&
|
||||
gunicorn mail_management.wsgi:application --bind 0.0.0.0:8000"
|
||||
volumes:
|
||||
- static_volume:/app/staticfiles
|
||||
- media_volume:/app/media
|
||||
ports:
|
||||
- "8000:8000"
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
volumes:
|
||||
static_volume:
|
||||
media_volume:
|
@@ -11,7 +11,7 @@ https://docs.djangoproject.com/en/5.2/ref/settings/
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import os
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
@@ -20,13 +20,13 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'django-insecure-u^7rwn!f0*brki9f46&lu8_lal=3_(1kykx#84dp^hx62923qr'
|
||||
SECRET_KEY = os.getenv("SECRET_KEY", 'django-insecure-u^7rwn!f0*brki9f46&lu8_lal=3_(1kykx#84dp^hx62923qr')
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
DEBUG = os.getenv('DEBUG', 'false').lower() == 'true'
|
||||
|
||||
ALLOWED_HOSTS: list[str] = os.getenv('ALLOWED_HOSTS', '').split(',') if os.getenv('ALLOWED_HOSTS') else ['*']
|
||||
CORS_ALLOWED_ORIGINS = os.getenv('CORS_ALLOWED_ORIGINS', '').split(',') if os.getenv('CORS_ALLOWED_ORIGINS') else []
|
||||
|
||||
# Application definition
|
||||
|
||||
@@ -39,17 +39,20 @@ INSTALLED_APPS = [
|
||||
'django.contrib.staticfiles',
|
||||
'ninja_extra',
|
||||
'ninja_jwt',
|
||||
'corsheaders',
|
||||
'api'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'mail_management.urls'
|
||||
@@ -119,6 +122,11 @@ USE_TZ = True
|
||||
# https://docs.djangoproject.com/en/5.2/howto/static-files/
|
||||
|
||||
STATIC_URL = 'static/'
|
||||
MEDIA_URL = '/media/'
|
||||
STATIC_ROOT = BASE_DIR / "staticfiles"
|
||||
MEDIA_ROOT = BASE_DIR / "media"
|
||||
|
||||
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
|
||||
|
@@ -5,8 +5,10 @@ description = "Add your description here"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"django>=5.2.1",
|
||||
"django-cors-headers>=4.7.0",
|
||||
"django-ninja>=1.4.1",
|
||||
"django-ninja-jwt>=5.3.7",
|
||||
"mypy>=1.15.0",
|
||||
"ruff>=0.11.10",
|
||||
"whitenoise>=6.9.0",
|
||||
]
|
||||
|
60
requirements.txt
Normal file
60
requirements.txt
Normal file
@@ -0,0 +1,60 @@
|
||||
# This file was autogenerated by uv via the following command:
|
||||
# uv pip compile pyproject.toml -o requirements.txt
|
||||
annotated-types==0.7.0
|
||||
# via pydantic
|
||||
asgiref==3.8.1
|
||||
# via
|
||||
# django
|
||||
# django-cors-headers
|
||||
# django-ninja-extra
|
||||
cffi==1.17.1
|
||||
# via cryptography
|
||||
contextlib2==21.6.0
|
||||
# via django-ninja-extra
|
||||
cryptography==45.0.3
|
||||
# via pyjwt
|
||||
django==5.2.1
|
||||
# via
|
||||
# mail-management (pyproject.toml)
|
||||
# django-cors-headers
|
||||
# django-ninja
|
||||
# django-ninja-extra
|
||||
# django-ninja-jwt
|
||||
django-cors-headers==4.7.0
|
||||
# via mail-management (pyproject.toml)
|
||||
django-ninja==1.4.1
|
||||
# via
|
||||
# mail-management (pyproject.toml)
|
||||
# django-ninja-extra
|
||||
django-ninja-extra==0.30.0
|
||||
# via django-ninja-jwt
|
||||
django-ninja-jwt==5.3.7
|
||||
# via mail-management (pyproject.toml)
|
||||
injector==0.22.0
|
||||
# via django-ninja-extra
|
||||
mypy==1.15.0
|
||||
# via mail-management (pyproject.toml)
|
||||
mypy-extensions==1.1.0
|
||||
# via mypy
|
||||
pycparser==2.22
|
||||
# via cffi
|
||||
pydantic==2.11.5
|
||||
# via django-ninja
|
||||
pydantic-core==2.33.2
|
||||
# via pydantic
|
||||
pyjwt==2.10.1
|
||||
# via django-ninja-jwt
|
||||
ruff==0.11.11
|
||||
# via mail-management (pyproject.toml)
|
||||
sqlparse==0.5.3
|
||||
# via django
|
||||
typing-extensions==4.13.2
|
||||
# via
|
||||
# mypy
|
||||
# pydantic
|
||||
# pydantic-core
|
||||
# typing-inspection
|
||||
typing-inspection==0.4.1
|
||||
# via pydantic
|
||||
whitenoise==6.9.0
|
||||
# via mail-management (pyproject.toml)
|
26
uv.lock
generated
26
uv.lock
generated
@@ -100,6 +100,19 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/90/92/7448697b5838b3a1c6e1d2d6a673e908d0398e84dc4f803a2ce11e7ffc0f/django-5.2.1-py3-none-any.whl", hash = "sha256:a9b680e84f9a0e71da83e399f1e922e1ab37b2173ced046b541c72e1589a5961", size = 8301833 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-cors-headers"
|
||||
version = "4.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "asgiref" },
|
||||
{ name = "django" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/93/6c/16f6cb6064c63074fd5b2bd494eb319afd846236d9c1a6c765946df2c289/django_cors_headers-4.7.0.tar.gz", hash = "sha256:6fdf31bf9c6d6448ba09ef57157db2268d515d94fc5c89a0a1028e1fc03ee52b", size = 21037 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/a2/7bcfff86314bd9dd698180e31ba00604001606efb518a06cca6833a54285/django_cors_headers-4.7.0-py3-none-any.whl", hash = "sha256:f1c125dcd58479fe7a67fe2499c16ee38b81b397463cf025f0e2c42937421070", size = 12794 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-ninja"
|
||||
version = "1.4.1"
|
||||
@@ -158,19 +171,23 @@ version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "django" },
|
||||
{ name = "django-cors-headers" },
|
||||
{ name = "django-ninja" },
|
||||
{ name = "django-ninja-jwt" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
{ name = "whitenoise" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "django", specifier = ">=5.2.1" },
|
||||
{ name = "django-cors-headers", specifier = ">=4.7.0" },
|
||||
{ name = "django-ninja", specifier = ">=1.4.1" },
|
||||
{ name = "django-ninja-jwt", specifier = ">=5.3.7" },
|
||||
{ name = "mypy", specifier = ">=1.15.0" },
|
||||
{ name = "ruff", specifier = ">=0.11.10" },
|
||||
{ name = "whitenoise", specifier = ">=6.9.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -330,3 +347,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be76
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "whitenoise"
|
||||
version = "6.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b9/cf/c15c2f21aee6b22a9f6fc9be3f7e477e2442ec22848273db7f4eb73d6162/whitenoise-6.9.0.tar.gz", hash = "sha256:8c4a7c9d384694990c26f3047e118c691557481d624f069b7f7752a2f735d609", size = 25920 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/64/b2/2ce9263149fbde9701d352bda24ea1362c154e196d2fda2201f18fc585d7/whitenoise-6.9.0-py3-none-any.whl", hash = "sha256:c8a489049b7ee9889617bb4c274a153f3d979e8f51d2efd0f5b403caf41c57df", size = 20161 },
|
||||
]
|
||||
|
Reference in New Issue
Block a user