Виконайте всі кроки по порядку перед першим деплоєм (інструкція відносно загальна, тому можуть бути додаткові кроки)
python -m venv env
env\Scripts\activate
⚠️ Важливо: переконайтеся, що саме це середовище обране як інтерпретатор у VS Code — натиснітьCtrl+Shift+P→ Python: Select Interpreter → оберітьenv. В Visual Studio 2026 - так само, через контекстне меню в Solution Explorer треба все перевірити!
1.2 Встановіть усі залежності в активоване середовище (версії на 20.05.2026, для вашого проєкту може бути +- інший список)
pip install Django==6.0.5
python.exe -m pip install --upgrade pip
pip install djangorestframework==3.17.1
pip install django-cors-headers==4.7.0
pip install django-filter==25.1
pip install requests==2.32.3
pip install Pillow==12.2.0
pip install gunicorn==23.0.0
pip install "whitenoise[brotli]==6.12.0"
pip install dj-database-url==2.3.0
pip install psycopg2-binary==2.9.12
pip install django-environ==0.12.0
pip install python-dotenv==1.2.2pip freeze > requirements.txtЯкщо після встановлення нових пакетів — завжди оновлюйте
requirements.txtцією командою!!!
Створіть файл .env у корені проєкту:
DEBUG=True
SECRET_KEY=lab#%!9bgg)qpnz+23*e&r#n9#qc#vks8&vg9yu49ax(^a6*r@python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
❌ Не комітьте цей файл! Він має бути у
.gitignore. На Render змінні передаються через Dashboard!
# середовище
.env
venv/
env/
__pycache__/
*.pyc
# зібрана статика (Render збере її сам)
staticfiles/
# база даних SQLite (на продакшені буде PostgreSQL)
db.sqlite3
# IDE
.idea/
.vscode/import os
import dj_database_url
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
# ── .env ──────────────────────────────────────────────────────────────────────
try:
from dotenv import load_dotenv
load_dotenv()
print("✅ .env файл успішно завантажено")
except ImportError:
print("⚠️ python-dotenv не встановлений")
# ── SECRET KEY ────────────────────────────────────────────────────────────────
SECRET_KEY = os.environ.get('SECRET_KEY')
if not SECRET_KEY:
raise Exception("❌ SECRET_KEY не знайдено! Перевірте файл .env")
# ── DEBUG ─────────────────────────────────────────────────────────────────────
DEBUG = os.environ.get('DEBUG', 'True').lower() == 'true'
# ── ALLOWED HOSTS ─────────────────────────────────────────────────────────────
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')
if not ALLOWED_HOSTS or ALLOWED_HOSTS == ['']:
ALLOWED_HOSTS = ['localhost', '127.0.0.1', '0.0.0.0']
# ── INSTALLED APPS ────────────────────────────────────────────────────────────
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# сторонні
'corsheaders',
'django_filters',
'rest_framework',
# наші апки
'app',
'api',
]
# ── MIDDLEWARE ────────────────────────────────────────────────────────────────
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # !!!
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # !!!
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'Rest.urls' # назва проєкта у вас буде своя, звісно
WSGI_APPLICATION = 'Rest.wsgi.application'
# ── DATABASE ──────────────────────────────────────────────────────────────────
if os.environ.get('DATABASE_URL'):
DATABASES = {
'default': dj_database_url.config(
conn_max_age=600,
conn_health_checks=True,
ssl_require=True,
)
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# ── TEMPLATES ─────────────────────────────────────────────────────────────────
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
# ── REST FRAMEWORK ────────────────────────────────────────────────────────────
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'api.pagination.DefaultCursorPagination',
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'anon': '10000/day',
'user': '10000/day',
},
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
],
}
# ── STATIC FILES ──────────────────────────────────────────────────────────────
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
# ── CORS ──────────────────────────────────────────────────────────────────────
CORS_ALLOW_ALL_ORIGINS = True # на продакшені краще обмежити
# ── SECURITY (тільки продакшн) ────────────────────────────────────────────────
if not DEBUG:
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
# ── INTERNATIONALIZATION ──────────────────────────────────────────────────────
LANGUAGE_CODE = 'uk'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# ── CACHE ─────────────────────────────────────────────────────────────────────
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
}Створіть у корені проєкту файл build.sh:
#!/usr/bin/env bash
# exit on error
set -o errexit
echo "Installing dependencies..."
pip install -r requirements.txt
echo "Collecting static files..."
python manage.py collectstatic --noinput --clear
echo "Running migrations..."
python manage.py migrate --noinput
echo "Build completed successfully!"
⚠️ Після створення файлу зробіть його виконуваним (для Linux/Mac або через Git Bash, на вінді цей крок пропускаємо):chmod +x build.sh
Створіть у корені проєкту файл render.yaml:
services:
- type: web
name: alexflow # тут можна поставити назву вашого сервісу на рендері, не принципово
env: python
plan: free
buildCommand: ./build.sh
startCommand: >
gunicorn Rest.wsgi:application --log-level info
envVars:
- key: SECRET_KEY
generateValue: true
sync: false
- key: DEBUG
value: "False"
- key: ALLOWED_HOSTS
value: ".onrender.com"
- key: PYTHON_VERSION
value: "3.14"
databases:
- name: my-django-db
databaseName: mydb
user: myuser
plan: free
⚠️ Зверніть увагу: блокdatabasesзнаходиться на одному рівні зservices, не всередині нього.
Shell на Render у безкоштовному плані — платний!!! Тому всі потрібні дії виконуються у Start Command.
./build.sh
(міграції та статика вже всередині build.sh)
python manage.py migrate && python manage.py shell -c "from django.contrib.auth import get_user_model; User=get_user_model(); User.objects.filter(username='alex').exists() or User.objects.create_superuser('alex','','1')" && python manage.py seed && gunicorn Rest.wsgi:application --log-level info
Ця команда при кожному старті:
- Виконує міграції (якщо є нові)
- Створює суперюзера
alex(якщо ще не існує, собі створіть інший логін та пароль) - Запускає seed (наповнення даними) - при кожному редеплої!!!
- Стартує Gunicorn
Перейдіть: Render Dashboard → ваш сервіс → Environment
| Змінна | Значення |
|---|---|
SECRET_KEY |
Натисніть Generate або вставте свій |
DEBUG |
False |
ALLOWED_HOSTS |
.onrender.com |
DATABASE_URL |
Додається автоматично після підключення PostgreSQL, руками писати не треба |
Відкрийте Git Bash у папці проєкту та виконайте по порядку:
# 1. Ініціалізація git (якщо ще не зроблено)
git init
# 2. Додаємо всі файли (з урахуванням .gitignore!)
git add .
# 3. Перший коміт
git commit -m "Initial commit"
# 4. Підключаємо GitHub-репозиторій (заміни на свій)
git remote add origin https://github.com/ВАШ_ЮЗЕРНЕЙМ/НАЗВА_РЕПО.git
# 5. Перейменовуємо гілку в main і пушимо
git branch -M main
git push -u origin mainЯкщо репозиторій вже існує і там є файли (наприклад, ліцензія):
# Спочатку підтягуємо те, що є на GitHub
git pull origin main --allow-unrelated-histories
# Потім пушимо свої зміни
git push -u origin main✅ Гілка обов'язково має називатися
main— саме її слухає Render!
-
venvстворено, активовано, інтерпретатор обраний у VS Code / VS 2026 / PyCharm - Усі пакети встановлені саме у
venv -
requirements.txtактуальний і міститьgunicorn,whitenoise,dj-database-url,psycopg2-binary -
build.shстворено та додано до репозиторію -
render.yamlстворено та налаштовано -
DEBUG = Falseчерез змінну середовища на рендері, в локальному проєкті залишаємо тру -
SECRET_KEYбереться зі змінної середовища -
ALLOWED_HOSTSмістить.onrender.com -
DATABASESналаштована черезdj-database-url -
WhiteNoiseMiddlewareпідключено післяSecurityMiddleware -
STATIC_ROOTвказано,collectstaticвиконується без помилок -
.envфайл у.gitignoreі не запушений - Гілка
main, всі зміни запушено
| Помилка | Причина | Рішення |
|---|---|---|
ModuleNotFoundError: No module named 'gunicorn' |
Gunicorn не у requirements.txt |
Додайте і перезапуште |
ALLOWED_HOSTS error |
Домен Render не вказано | Додайте .onrender.com |
| Статика не завантажується | WhiteNoise не підключено або стоїть не там | Перевірте порядок у MIDDLEWARE |
django.db.utils.OperationalError |
Міграції не виконано | Перевірте build.sh або Start Command |
Invalid HTTP_HOST header |
Змінна ALLOWED_HOSTS порожня |
Перевірте Environment Variables на Render |
./build.sh: Permission denied |
Файл не є виконуваним | Виконайте chmod +x build.sh і перезапуште |
Підказка: після кожного деплою перевіряйте логи у Render Dashboard → Logs. Більшість проблем видно там одразу. Успіхів :)