aboutsummaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
authorMatthew Lemon <lemon@matthewlemon.com>2020-01-19 15:57:06 +0000
committerMatthew Lemon <lemon@matthewlemon.com>2020-01-19 15:57:06 +0000
commit9d76a3c52b8310726ec09e0262813f0438c21df6 (patch)
tree4acf47dce6c3aa75f8ad7c5cb56fe6486c2d64a7 /config
init commit - from cookiecutter
Diffstat (limited to 'config')
-rw-r--r--config/__init__.py0
-rw-r--r--config/settings/__init__.py0
-rw-r--r--config/settings/base.py268
-rw-r--r--config/settings/local.py54
-rw-r--r--config/settings/production.py180
-rw-r--r--config/settings/test.py51
-rw-r--r--config/urls.py45
-rw-r--r--config/wsgi.py39
8 files changed, 637 insertions, 0 deletions
diff --git a/config/__init__.py b/config/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/__init__.py
diff --git a/config/settings/__init__.py b/config/settings/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/settings/__init__.py
diff --git a/config/settings/base.py b/config/settings/base.py
new file mode 100644
index 0000000..5dea850
--- /dev/null
+++ b/config/settings/base.py
@@ -0,0 +1,268 @@
+"""
+Base settings to build other settings files upon.
+"""
+
+import environ
+
+ROOT_DIR = (
+ environ.Path(__file__) - 3
+) # (ctrack/config/settings/base.py - 3 = ctrack/)
+APPS_DIR = ROOT_DIR.path("ctrack")
+
+env = environ.Env()
+
+READ_DOT_ENV_FILE = env.bool("DJANGO_READ_DOT_ENV_FILE", default=False)
+if READ_DOT_ENV_FILE:
+ # OS environment variables take precedence over variables from .env
+ env.read_env(str(ROOT_DIR.path(".env")))
+
+# GENERAL
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#debug
+DEBUG = env.bool("DJANGO_DEBUG", False)
+# Local time zone. Choices are
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# though not all of them may be available with every OS.
+# In Windows, this must be set to your system time zone.
+TIME_ZONE = "UTC"
+# https://docs.djangoproject.com/en/dev/ref/settings/#language-code
+LANGUAGE_CODE = "en-us"
+# https://docs.djangoproject.com/en/dev/ref/settings/#site-id
+SITE_ID = 1
+# https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
+USE_I18N = True
+# https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
+USE_L10N = True
+# https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
+USE_TZ = True
+# https://docs.djangoproject.com/en/dev/ref/settings/#locale-paths
+LOCALE_PATHS = [ROOT_DIR.path("locale")]
+
+# DATABASES
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#databases
+
+DATABASES = {
+ "default": env.db("DATABASE_URL", default="postgres:///ctrack")
+}
+DATABASES["default"]["ATOMIC_REQUESTS"] = True
+
+# URLS
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf
+ROOT_URLCONF = "config.urls"
+# https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
+WSGI_APPLICATION = "config.wsgi.application"
+
+# APPS
+# ------------------------------------------------------------------------------
+DJANGO_APPS = [
+ "django.contrib.auth",
+ "django.contrib.contenttypes",
+ "django.contrib.sessions",
+ "django.contrib.sites",
+ "django.contrib.messages",
+ "django.contrib.staticfiles",
+ # "django.contrib.humanize", # Handy template tags
+ "django.contrib.admin",
+]
+THIRD_PARTY_APPS = [
+ "crispy_forms",
+ "allauth",
+ "allauth.account",
+ "allauth.socialaccount",
+ "rest_framework",
+]
+
+LOCAL_APPS = [
+ "ctrack.users.apps.UsersConfig",
+ # Your stuff: custom apps go here
+]
+# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
+INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
+
+# MIGRATIONS
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#migration-modules
+MIGRATION_MODULES = {"sites": "ctrack.contrib.sites.migrations"}
+
+# AUTHENTICATION
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#authentication-backends
+AUTHENTICATION_BACKENDS = [
+ "django.contrib.auth.backends.ModelBackend",
+ "allauth.account.auth_backends.AuthenticationBackend",
+]
+# https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model
+AUTH_USER_MODEL = "users.User"
+# https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url
+LOGIN_REDIRECT_URL = "users:redirect"
+# https://docs.djangoproject.com/en/dev/ref/settings/#login-url
+LOGIN_URL = "account_login"
+
+# PASSWORDS
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers
+PASSWORD_HASHERS = [
+ # https://docs.djangoproject.com/en/dev/topics/auth/passwords/#using-argon2-with-django
+ "django.contrib.auth.hashers.Argon2PasswordHasher",
+ "django.contrib.auth.hashers.PBKDF2PasswordHasher",
+ "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
+ "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
+]
+# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators
+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"},
+]
+
+# MIDDLEWARE
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#middleware
+MIDDLEWARE = [
+ "django.middleware.security.SecurityMiddleware",
+ "django.contrib.sessions.middleware.SessionMiddleware",
+ "django.middleware.locale.LocaleMiddleware",
+ "django.middleware.common.CommonMiddleware",
+ "django.middleware.csrf.CsrfViewMiddleware",
+ "django.contrib.auth.middleware.AuthenticationMiddleware",
+ "django.contrib.messages.middleware.MessageMiddleware",
+ "django.middleware.common.BrokenLinkEmailsMiddleware",
+ "django.middleware.clickjacking.XFrameOptionsMiddleware",
+]
+
+# STATIC
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#static-root
+STATIC_ROOT = str(ROOT_DIR("staticfiles"))
+# https://docs.djangoproject.com/en/dev/ref/settings/#static-url
+STATIC_URL = "/static/"
+# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
+STATICFILES_DIRS = [str(APPS_DIR.path("static"))]
+# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
+STATICFILES_FINDERS = [
+ "django.contrib.staticfiles.finders.FileSystemFinder",
+ "django.contrib.staticfiles.finders.AppDirectoriesFinder",
+]
+
+# MEDIA
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#media-root
+MEDIA_ROOT = str(APPS_DIR("media"))
+# https://docs.djangoproject.com/en/dev/ref/settings/#media-url
+MEDIA_URL = "/media/"
+
+# TEMPLATES
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#templates
+TEMPLATES = [
+ {
+ # https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
+ # https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
+ "DIRS": [str(APPS_DIR.path("templates"))],
+ "OPTIONS": {
+ # https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
+ # https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
+ "loaders": [
+ "django.template.loaders.filesystem.Loader",
+ "django.template.loaders.app_directories.Loader",
+ ],
+ # https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
+ "context_processors": [
+ "django.template.context_processors.debug",
+ "django.template.context_processors.request",
+ "django.contrib.auth.context_processors.auth",
+ "django.template.context_processors.i18n",
+ "django.template.context_processors.media",
+ "django.template.context_processors.static",
+ "django.template.context_processors.tz",
+ "django.contrib.messages.context_processors.messages",
+ "ctrack.utils.context_processors.settings_context",
+ ],
+ },
+ }
+]
+# http://django-crispy-forms.readthedocs.io/en/latest/install.html#template-packs
+CRISPY_TEMPLATE_PACK = "bootstrap4"
+
+# FIXTURES
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#fixture-dirs
+FIXTURE_DIRS = (str(APPS_DIR.path("fixtures")),)
+
+# SECURITY
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-httponly
+SESSION_COOKIE_HTTPONLY = True
+# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-httponly
+CSRF_COOKIE_HTTPONLY = True
+# https://docs.djangoproject.com/en/dev/ref/settings/#secure-browser-xss-filter
+SECURE_BROWSER_XSS_FILTER = True
+# https://docs.djangoproject.com/en/dev/ref/settings/#x-frame-options
+X_FRAME_OPTIONS = "DENY"
+
+# EMAIL
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
+EMAIL_BACKEND = env(
+ "DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.smtp.EmailBackend"
+)
+# https://docs.djangoproject.com/en/2.2/ref/settings/#email-timeout
+EMAIL_TIMEOUT = 5
+
+# ADMIN
+# ------------------------------------------------------------------------------
+# Django Admin URL.
+ADMIN_URL = "admin/"
+# https://docs.djangoproject.com/en/dev/ref/settings/#admins
+ADMINS = [("""Matt Lemon""", "matt@matthewlemon.com")]
+# https://docs.djangoproject.com/en/dev/ref/settings/#managers
+MANAGERS = ADMINS
+
+# 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"]},
+}
+
+
+# django-allauth
+# ------------------------------------------------------------------------------
+ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True)
+# https://django-allauth.readthedocs.io/en/latest/configuration.html
+ACCOUNT_AUTHENTICATION_METHOD = "username"
+# https://django-allauth.readthedocs.io/en/latest/configuration.html
+ACCOUNT_EMAIL_REQUIRED = True
+# https://django-allauth.readthedocs.io/en/latest/configuration.html
+ACCOUNT_EMAIL_VERIFICATION = "mandatory"
+# https://django-allauth.readthedocs.io/en/latest/configuration.html
+ACCOUNT_ADAPTER = "ctrack.users.adapters.AccountAdapter"
+# https://django-allauth.readthedocs.io/en/latest/configuration.html
+SOCIALACCOUNT_ADAPTER = "ctrack.users.adapters.SocialAccountAdapter"
+
+
+# Your stuff...
+# ------------------------------------------------------------------------------
diff --git a/config/settings/local.py b/config/settings/local.py
new file mode 100644
index 0000000..311fb77
--- /dev/null
+++ b/config/settings/local.py
@@ -0,0 +1,54 @@
+from .base import * # noqa
+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="VWMf2IWTRhWmbM8Bu3Opy7GZa9auuQpIYLNltIEUbutegXp610DWCRQeW8AHWRZD",
+)
+# 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",
+ "LOCATION": "",
+ }
+}
+
+# EMAIL
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
+EMAIL_BACKEND = env(
+ "DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend"
+)
+
+# django-debug-toolbar
+# ------------------------------------------------------------------------------
+# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#prerequisites
+INSTALLED_APPS += ["debug_toolbar"] # noqa F405
+# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#middleware
+MIDDLEWARE += ["debug_toolbar.middleware.DebugToolbarMiddleware"] # noqa F405
+# https://django-debug-toolbar.readthedocs.io/en/latest/configuration.html#debug-toolbar-config
+DEBUG_TOOLBAR_CONFIG = {
+ "DISABLE_PANELS": ["debug_toolbar.panels.redirects.RedirectsPanel"],
+ "SHOW_TEMPLATE_CONTEXT": True,
+}
+# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#internal-ips
+INTERNAL_IPS = ["127.0.0.1", "10.0.2.2"]
+
+
+# django-extensions
+# ------------------------------------------------------------------------------
+# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration
+INSTALLED_APPS += ["django_extensions"] # noqa F405
+
+# Your stuff...
+# ------------------------------------------------------------------------------
diff --git a/config/settings/production.py b/config/settings/production.py
new file mode 100644
index 0000000..ffce376
--- /dev/null
+++ b/config/settings/production.py
@@ -0,0 +1,180 @@
+from .base import * # noqa
+from .base import env
+
+# GENERAL
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
+SECRET_KEY = env("DJANGO_SECRET_KEY")
+# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
+ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["ctrackdft.net"])
+
+# DATABASES
+# ------------------------------------------------------------------------------
+DATABASES["default"] = env.db("DATABASE_URL") # noqa F405
+DATABASES["default"]["ATOMIC_REQUESTS"] = True # noqa F405
+DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60) # noqa F405
+
+# CACHES
+# ------------------------------------------------------------------------------
+CACHES = {
+ "default": {
+ "BACKEND": "django_redis.cache.RedisCache",
+ "LOCATION": env("REDIS_URL"),
+ "OPTIONS": {
+ "CLIENT_CLASS": "django_redis.client.DefaultClient",
+ # Mimicing memcache behavior.
+ # http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
+ "IGNORE_EXCEPTIONS": True,
+ },
+ }
+}
+
+# SECURITY
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header
+SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
+# https://docs.djangoproject.com/en/dev/ref/settings/#secure-ssl-redirect
+SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True)
+# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure
+SESSION_COOKIE_SECURE = True
+# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-secure
+CSRF_COOKIE_SECURE = True
+# https://docs.djangoproject.com/en/dev/topics/security/#ssl-https
+# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-seconds
+# TODO: set this to 60 seconds first and then to 518400 once you prove the former works
+SECURE_HSTS_SECONDS = 60
+# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains
+SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(
+ "DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True
+)
+# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload
+SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True)
+# https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff
+SECURE_CONTENT_TYPE_NOSNIFF = env.bool(
+ "DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True
+)
+
+# STORAGES
+# ------------------------------------------------------------------------------
+# https://django-storages.readthedocs.io/en/latest/#installation
+INSTALLED_APPS += ["storages"] # noqa F405
+GS_BUCKET_NAME = env("DJANGO_GCP_STORAGE_BUCKET_NAME")
+GS_DEFAULT_ACL = "publicRead"
+# STATIC
+# ------------------------
+STATICFILES_STORAGE = "config.settings.production.StaticRootGoogleCloudStorage"
+COLLECTFAST_STRATEGY = "collectfast.strategies.gcloud.GoogleCloudStrategy"
+STATIC_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/"
+# MEDIA
+# ------------------------------------------------------------------------------
+from storages.backends.gcloud import GoogleCloudStorage # noqa E402
+
+
+class StaticRootGoogleCloudStorage(GoogleCloudStorage):
+ location = "static"
+ default_acl = "publicRead"
+
+
+class MediaRootGoogleCloudStorage(GoogleCloudStorage):
+ location = "media"
+ file_overwrite = False
+
+
+DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootGoogleCloudStorage"
+MEDIA_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/"
+
+# TEMPLATES
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#templates
+TEMPLATES[-1]["OPTIONS"]["loaders"] = [ # type: ignore[index] # noqa F405
+ (
+ "django.template.loaders.cached.Loader",
+ [
+ "django.template.loaders.filesystem.Loader",
+ "django.template.loaders.app_directories.Loader",
+ ],
+ )
+]
+
+# EMAIL
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email
+DEFAULT_FROM_EMAIL = env(
+ "DJANGO_DEFAULT_FROM_EMAIL", default="ctrack <noreply@ctrackdft.net>"
+)
+# https://docs.djangoproject.com/en/dev/ref/settings/#server-email
+SERVER_EMAIL = env("DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL)
+# https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix
+EMAIL_SUBJECT_PREFIX = env(
+ "DJANGO_EMAIL_SUBJECT_PREFIX", default="[ctrack]"
+)
+
+# ADMIN
+# ------------------------------------------------------------------------------
+# Django Admin URL regex.
+ADMIN_URL = env("DJANGO_ADMIN_URL")
+
+# Anymail (Mailgun)
+# ------------------------------------------------------------------------------
+# https://anymail.readthedocs.io/en/stable/installation/#installing-anymail
+INSTALLED_APPS += ["anymail"] # noqa F405
+EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend"
+# https://anymail.readthedocs.io/en/stable/installation/#anymail-settings-reference
+ANYMAIL = {
+ "MAILGUN_API_KEY": env("MAILGUN_API_KEY"),
+ "MAILGUN_SENDER_DOMAIN": env("MAILGUN_DOMAIN"),
+ "MAILGUN_API_URL": env("MAILGUN_API_URL", default="https://api.mailgun.net/v3"),
+}
+
+# Collectfast
+# ------------------------------------------------------------------------------
+# https://github.com/antonagestam/collectfast#installation
+INSTALLED_APPS = ["collectfast"] + INSTALLED_APPS # 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.
+# A sample logging configuration. The only tangible logging
+# performed by this configuration is to send an email to
+# the site admins on every HTTP 500 error when DEBUG=False.
+LOGGING = {
+ "version": 1,
+ "disable_existing_loggers": False,
+ "filters": {"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"}},
+ "formatters": {
+ "verbose": {
+ "format": "%(levelname)s %(asctime)s %(module)s "
+ "%(process)d %(thread)d %(message)s"
+ }
+ },
+ "handlers": {
+ "mail_admins": {
+ "level": "ERROR",
+ "filters": ["require_debug_false"],
+ "class": "django.utils.log.AdminEmailHandler",
+ },
+ "console": {
+ "level": "DEBUG",
+ "class": "logging.StreamHandler",
+ "formatter": "verbose",
+ },
+ },
+ "root": {"level": "INFO", "handlers": ["console"]},
+ "loggers": {
+ "django.request": {
+ "handlers": ["mail_admins"],
+ "level": "ERROR",
+ "propagate": True,
+ },
+ "django.security.DisallowedHost": {
+ "level": "ERROR",
+ "handlers": ["console", "mail_admins"],
+ "propagate": True,
+ },
+ },
+}
+
+# Your stuff...
+# ------------------------------------------------------------------------------
diff --git a/config/settings/test.py b/config/settings/test.py
new file mode 100644
index 0000000..718cbdb
--- /dev/null
+++ b/config/settings/test.py
@@ -0,0 +1,51 @@
+"""
+With these settings, tests run faster.
+"""
+
+from .base import * # noqa
+from .base import env
+
+# GENERAL
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
+SECRET_KEY = env(
+ "DJANGO_SECRET_KEY",
+ default="YjL0TsaerybdulEyjn4hxDZ3207sgDVpr7NOoSuzAJHMAL5GNbHdKwFrsyptQ0Je",
+)
+# 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",
+ "LOCATION": "",
+ }
+}
+
+# PASSWORDS
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers
+PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"]
+
+# TEMPLATES
+# ------------------------------------------------------------------------------
+TEMPLATES[-1]["OPTIONS"]["loaders"] = [ # type: ignore[index] # noqa F405
+ (
+ "django.template.loaders.cached.Loader",
+ [
+ "django.template.loaders.filesystem.Loader",
+ "django.template.loaders.app_directories.Loader",
+ ],
+ )
+]
+
+# EMAIL
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
+EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
+
+# Your stuff...
+# ------------------------------------------------------------------------------
diff --git a/config/urls.py b/config/urls.py
new file mode 100644
index 0000000..2e9f883
--- /dev/null
+++ b/config/urls.py
@@ -0,0 +1,45 @@
+from django.conf import settings
+from django.urls import include, path
+from django.conf.urls.static import static
+from django.contrib import admin
+from django.views.generic import TemplateView
+from django.views import defaults as default_views
+
+urlpatterns = [
+ path("", TemplateView.as_view(template_name="pages/home.html"), name="home"),
+ path(
+ "about/", TemplateView.as_view(template_name="pages/about.html"), name="about"
+ ),
+ # Django Admin, use {% url 'admin:index' %}
+ path(settings.ADMIN_URL, admin.site.urls),
+ # User management
+ path("users/", include("ctrack.users.urls", namespace="users")),
+ path("accounts/", include("allauth.urls")),
+ # Your stuff: custom urls includes go here
+] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+
+if settings.DEBUG:
+ # This allows the error pages to be debugged during development, just visit
+ # these url in browser to see how these error pages look like.
+ urlpatterns += [
+ path(
+ "400/",
+ default_views.bad_request,
+ kwargs={"exception": Exception("Bad Request!")},
+ ),
+ path(
+ "403/",
+ default_views.permission_denied,
+ kwargs={"exception": Exception("Permission Denied")},
+ ),
+ path(
+ "404/",
+ default_views.page_not_found,
+ kwargs={"exception": Exception("Page not Found")},
+ ),
+ path("500/", default_views.server_error),
+ ]
+ if "debug_toolbar" in settings.INSTALLED_APPS:
+ import debug_toolbar
+
+ urlpatterns = [path("__debug__/", include(debug_toolbar.urls))] + urlpatterns
diff --git a/config/wsgi.py b/config/wsgi.py
new file mode 100644
index 0000000..e0c17b0
--- /dev/null
+++ b/config/wsgi.py
@@ -0,0 +1,39 @@
+"""
+WSGI config for ctrack project.
+
+This module contains the WSGI application used by Django's development server
+and any production WSGI deployments. It should expose a module-level variable
+named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
+this application via the ``WSGI_APPLICATION`` setting.
+
+Usually you will have the standard Django WSGI application here, but it also
+might make sense to replace the whole Django WSGI application with a custom one
+that later delegates to the Django one. For example, you could introduce WSGI
+middleware here, or combine a Django application with an application of another
+framework.
+
+"""
+import os
+import sys
+
+from django.core.wsgi import get_wsgi_application
+
+# This allows easy placement of apps within the interior
+# ctrack directory.
+app_path = os.path.abspath(
+ os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)
+)
+sys.path.append(os.path.join(app_path, "ctrack"))
+# 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")
+
+# This application object is used by any WSGI server configured to use this
+# file. This includes Django's development server, if the WSGI_APPLICATION
+# setting points here.
+application = get_wsgi_application()
+# Apply WSGI middleware here.
+# from helloworld.wsgi import HelloWorldApplication
+# application = HelloWorldApplication(application)