Hello!
I have deployed my project on Heroku and at first everything worked fine. The site was live.
But for some reason (I don’t remember what I did) I started to get error 500 on almost all URLs. I’ve created custom error pages to display.
Neither the Heroku logs or Django throws any form of errors. The only thing I see on when I run this command:
heroku logs
is:
2024-11-23T23:31:34.129978+00:00 heroku[router]: at=info method=GET path="/" host=www.exampel.se request_id=4557ecdc-110e-4932-b353-f9019f2804d9 fwd="213.204.198.19" dyno=web.1 connect=2ms service=235ms status=500 bytes=7986 protocol=https
I will share my settings file here if someone could please take a look and hopefully have a sharper eye than I do. Also, please feel free to share some feedback on my settings:
General settings:
import os
from pathlib import Path
from django.urls import reverse_lazy
from dotenv import load_dotenv
BASE_DIR = Path(__file__).resolve().parent.parent
load_dotenv()
INSTALLED_APPS = [
'whitenoise.runserver_nostatic', # Must be at the top
'anymail',
'daphne',
'channels',
'main_app',
'auth_app',
'profile_app',
'settings_app',
'messages_app',
'media_app',
'diary_app',
'hitcount',
'debug_toolbar',
'django.contrib.admindocs',
'django_filters',
'crispy_forms',
'constrainedfilefield',
'schema_graph',
# 'silk',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
# The debug middleware must be placed first
"debug_toolbar.middleware.DebugToolbarMiddleware",
'django.middleware.security.SecurityMiddleware',
'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',
'django.contrib.admindocs.middleware.XViewMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# 'silk.middleware.SilkyMiddleware',
]
AUTHENTICATION_BACKENDS = ["django.contrib.auth.backends.AllowAllUsersModelBackend"]
ROOT_URLCONF = 'my_project.urls'
STORAGES = {
"default": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
},
"staticfiles": {
"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
},
}
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'),],
'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',
'my_project.context_processors.django_env.django_env',
],
},
},
]
WSGI_APPLICATION = 'my_project.wsgi.application'
ASGI_APPLICATION = "my_project.asgi.application"
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
SECRET_KEY = os.environ.get("SECRET_KEY")
AUTH_USER_MODEL = 'main_app.Member'
HITCOUNT_KEEP_HIT_ACTIVE = {'days': 365} # Repeated hits on the same object are not counted for a year.
HITCOUNT_HITS_PER_IP_LIMIT = 0 # Unlimited numner of hits from a certain IP-address
HITCOUNT_KEEP_HIT_IN_DATABASE = {'days': 365} # The samme time limit as each post exist
LANGUAGE_CODE = 'sv-se'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
STATIC_URL = '/static/'
MEDIA_URL = "/user_uploads/"
STATIC_ROOT = os.path.join(BASE_DIR.parent, "staticfiles/") # Path must be absolute
MEDIA_ROOT = os.path.join(BASE_DIR.parent, 'user_uploads/') # Path must be absolute
STATICFILES_DIRS = [os.path.join(BASE_DIR.parent, "static")]
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
DEFAULT_FROM_EMAIL = os.environ.get("DEFAULT_FROM_EMAIL")
SERVER_EMAIL = os.environ.get("SERVER_EMAIL")
LOGIN_REDIRECT_URL = reverse_lazy("main_app:roomsPage")
LOGIN_URL = reverse_lazy("auth_app:signin")
LOGOUT_URL = reverse_lazy("auth_app:signin")
LOGOUT_REDIRECT_URL = reverse_lazy("auth_app:signin")
ALLOWED_IMAGE_EXTENSIONS = ["JPEG", "JPG", "PNG"]
ALLOWED_VIDEO_EXTENSIONS = []
ALLOWED_NUMBERS_OF_IMAGES = 10
ALLOWED_NUMBER_OF_VIDEOS = 10
DATA_UPLOAD_MAX_NUMBER_FILES = 10
MAX_UPLOAD_VIDEO_SIZE = 104_857_600 # 100 MB
MAX_UPLOAD_PHOTO_SIZE = 104_857_6 # 1 MB
MAX_IMAGE_HEIGHT = 2000 # 2000 pixels
MAX_IMAGE_WIDTH = 2000 # 2000 pixels
ALLOWED_IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/jpg']
ALLOWED_VIDEO_TYPES = ['video/mp4', 'video/quicktime', 'video/x-msvideo', 'video/x-matroska']
MAX_PROFILE_VISITORS = 30
MAX_ROOM_PER_USER = 10 # Max number of rooms per user instance
MAX_CHATMESSAGE_LENGTH = 250
MAX_TEXTFIELD_LENGTH = 500
URL_EXTENSION_LENGTH = 10
MAX_NUMBER_OF_ONLINE_MEMBERS_TO_DISPLAY = 150
PROFILE_DESCRIPTION_LENGTH = 2000
GROUP_PROFILE_INTRODUCTION_LENGTH = 3000
GROUP_PROFILE_RULES_LENGTH = 3000
GROUP_PROFILE_WISHES_LENGTH = 3000
DATA_RETENTION_PERIOD = 90 # days
DELETE_SIGNIN_HISTORY_AFTER = 7
DELETE_ACCOUNT_OLDER_THAN = 730 # 2 years
DELETE_ROOMS_OLDER_THAN = 365 # 1 year
DELETE_CHATROOMS_OLDER_THAN = 365 # 1 year
MAX_DIARY_LENGTH = 3000
DATE_INPUT_FORMATS = ["%Y-%m-%d"]
DATETIME_INPUT_FORMATS = ["%Y-%m-%d %H:%M"]
MAGIC_FILE_PATH = r"C:\Windows\System32\magic.mgc"
```
```
Production settings:
```
import dj_database_url
from .settings import *
DEBUG = False
ALLOWED_HOSTS = [".exampel.com", ".my-project-f330a5d3af70.herokuapp.com"]
ADMINS = [("admin", os.environ.get("ADMIN_EMAIL_ADDRESS"))]
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_SECONDS = 31536000 # 1 year
SECURE_HSTS_PRELOAD = True
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
GEOIP_PATH = os.path.join(BASE_DIR.parent, 'geoip/')
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
EMAIL_BACKEND = 'anymail.backends.mailgun.EmailBackend'
ANYMAIL = {
'MAILGUN_API_KEY': os.environ.get("MAILGUN_API_KEY"),
'MAILGUN_SENDER_DOMAIN': os.environ.get("MAILGUN_SENDER_DOMAIN"),
'MAILGUN_API_URL': os.environ.get("MAILGUN_API_URL"),
}
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = os.environ.get("DEFAULT_FROM_EMAIL")
SERVER_EMAIL = os.environ.get("SERVER_EMAIL")
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'
SESSION_COOKIE_AGE = 7200 # 2 h
SESSION_COOKIE_SECURE = True
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
"LOCATION": os.environ.get("MEMCACHEDCLOUD_SERVERS"),
}
}
DATABASES = {
"default": dj_database_url.config(
conn_max_age=600,
conn_health_checks=True,
ssl_require=True,
),
}
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [{"address": os.environ.get("REDIS_CLOUD_URL")}],
},
},
}
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '[%(asctime)s] %(levelname)s %(name)s: %(message)s'
},
'verbose': {
'format': '[%(asctime)s] - %(levelname)s - %(name)s - %(module)s - %(process)d %(thread)d: %(message)s'
},
},
'handlers': {
'file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(BASE_DIR, "logg-files", "production", "prod-log-file"),
'maxBytes': 1024*1024*5, # 5MB
'backupCount': 5,
'formatter': 'verbose',
},
'user_signin_history': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(BASE_DIR, "logg-files", "production", "signInHistory"),
'maxBytes': 1024*1024*5, # 5MB
'backupCount': 5,
'formatter': 'verbose',
},
'deletion_failed_handler': {
'level': 'ERROR',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(BASE_DIR, "logg-files", "production", "account_deletion_failed_loggs"),
'maxBytes': 1024*1024*5, # 5MB
'backupCount': 5,
'formatter': 'verbose',
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'formatter': 'verbose',
'include_html': True,
},
'password_reset': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(BASE_DIR, "logg-files", "production", "password_reset_request"),
'maxBytes': 1024*1024*5, # 5MB
'backupCount': 5,
'formatter': 'verbose',
},
'successful_sigins': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(BASE_DIR, "logg-files", "production", "successful_signins"),
'maxBytes': 1024*1024*5, # 5MB
'backupCount': 5,
'formatter': 'verbose',
},
'failed_signins': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(BASE_DIR, "logg-files", "production", "failed_signins"),
'maxBytes': 1024*1024*5, # 5MB
'backupCount': 5,
'formatter': 'verbose',
},
'email_confirmation_error': {
'level': 'ERROR',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(BASE_DIR, "logg-files", "production", "email_account_registered_confi_error"),
'maxBytes': 1024*1024*5, # 5MB
'backupCount': 5,
'formatter': 'verbose',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'INFO',
'propagate': True,
},
'django.request': {
'handlers': ['file', 'mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'django.security': {
'handlers': ['file', 'mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'successful_signins': {
'handlers': ['successful_sigins'],
'level': 'INFO',
'propagate': False,
},
'failed_signins': {
'handlers': ['failed_signins'],
'level': 'INFO',
'propagate': False,
},
'password_reset_request': {
'handlers': ['password_reset'],
'level': 'INFO',
'propagate': False,
},
'deletion_logger': {
'handler': ['deletion_failed_handler'],
'level': 'ERROR',
'propagate': False,
},
'email_confirmation_error': {
'handler': ['email_confirmation_error'],
'level': 'ERROR',
'propagate': False,
},
},
}
```