We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Make the docker compose file self documenting
### It should be made clear in the docker compose file:
- The prerequisites required to run the file
- How to actually run the file
- The purpose for each of the environment variables used by different containers
- Their recommended/suggested/default values

### Goals:
- The need of referring to our docs for this installation method by the user should be eliminated upon resolving this issue.   
- The need of user to add variables in the `.env` file should be removed and instead these variables should be customizable in the compose file itself.

### Nice to haves:
- Make possible mounting folders as volumes to increase the visibility of the data being stored on user device. This is also useful if the data is being used by some other service on the host device. 
- Consider removing watchtower and push user to update manually instead.

### Additional context
<!-- Add any other context or screenshots about the feature request here.-->
Related to #3166 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `config/settings/common_settings.py`
Content:
```
1 """
2 Base settings to build other settings files upon.
3 
4 Generated by 'django-admin startproject' using Django 3.1.7.
5 
6 For more information on this file, see
7 https://docs.djangoproject.com/en/3.1/topics/settings/
8 
9 For the full list of settings and their values, see
10 https://docs.djangoproject.com/en/3.1/ref/settings/
11 """
12 
13 import os
14 from pathlib import Path
15 
16 from decouple import Csv, config as decouple_config
17 from dj_database_url import parse as db_url
18 from django.utils.translation import gettext_lazy
19 
20 
21 # We use a 'tuple' with pipes as delimiters as decople naively splits the global
22 # variables on commas when casting to Csv()
23 def pipe_delim(pipe_string):
24     # Remove opening and closing brackets
25     pipe_string = pipe_string[1:-1]
26     # Split on pipe delim
27     return pipe_string.split("|")
28 
29 
30 # Build paths inside the project like this: BASE_DIR / 'subdir'.
31 BASE_DIR = Path(__file__).resolve().parent.parent.parent
32 
33 # Application definition
34 
35 INSTALLED_APPS = [
36     "django.contrib.admin",
37     "django.contrib.auth",
38     "django.contrib.contenttypes",
39     "django.contrib.sessions",
40     "django.contrib.messages",
41     "whitenoise.runserver_nostatic",
42     "django.contrib.staticfiles",
43     "rest_framework",
44     "django_filters",
45     "django_property_filter",
46     "drf_spectacular",
47     "mathesar",
48 ]
49 
50 MIDDLEWARE = [
51     "django.middleware.security.SecurityMiddleware",
52     "whitenoise.middleware.WhiteNoiseMiddleware",
53     "django.contrib.sessions.middleware.SessionMiddleware",
54     "django.middleware.locale.LocaleMiddleware",
55     "django.middleware.common.CommonMiddleware",
56     "django.middleware.csrf.CsrfViewMiddleware",
57     "django.contrib.auth.middleware.AuthenticationMiddleware",
58     "django.contrib.messages.middleware.MessageMiddleware",
59     "django.middleware.clickjacking.XFrameOptionsMiddleware",
60     "mathesar.middleware.CursorClosedHandlerMiddleware",
61     "mathesar.middleware.PasswordChangeNeededMiddleware",
62     'django_userforeignkey.middleware.UserForeignKeyMiddleware',
63     'django_request_cache.middleware.RequestCacheMiddleware',
64 ]
65 
66 ROOT_URLCONF = "config.urls"
67 
68 TEMPLATES = [
69     {
70         "BACKEND": "django.template.backends.django.DjangoTemplates",
71         "DIRS": [],
72         "APP_DIRS": True,
73         "OPTIONS": {
74             "context_processors": [
75                 "config.context_processors.frontend_settings",
76                 "django.template.context_processors.debug",
77                 "django.template.context_processors.request",
78                 "django.contrib.auth.context_processors.auth",
79                 "django.contrib.messages.context_processors.messages",
80                 "mathesar.template_context_processors.base_template_extensions.script_extension_templates"
81             ],
82         },
83     },
84 ]
85 
86 WSGI_APPLICATION = "config.wsgi.application"
87 
88 # Database
89 # https://docs.djangoproject.com/en/3.1/ref/settings/#databases
90 
91 # TODO: Add to documentation that database keys should not be than 128 characters.
92 
93 # MATHESAR_DATABASES should be of the form '({db_name}|{db_url}), ({db_name}|{db_url})'
94 # See pipe_delim above for why we use pipes as delimiters
95 DATABASES = {
96     db_key: db_url(url_string)
97     for db_key, url_string in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim))
98 }
99 
100 DATABASES[decouple_config('DJANGO_DATABASE_KEY', default="default")] = decouple_config('DJANGO_DATABASE_URL', cast=db_url, default='sqlite:///db.sqlite3')
101 
102 for db_key, db_dict in DATABASES.items():
103     # Engine should be '.postgresql' or '.postgresql_psycopg2' for all db(s),
104     # however for the internal 'default' db 'sqlite3' can be used.
105     if not db_dict['ENGINE'].startswith('django.db.backends.postgresql') and db_key != 'default':
106         raise ValueError(
107             f"{db_key} is not a PostgreSQL database. "
108             f"{db_dict['ENGINE']} found for {db_key}'s engine."
109         )
110 
111 # pytest-django will create a new database named 'test_{DATABASES[table_db]['NAME']}'
112 # and use it for our API tests if we don't specify DATABASES[table_db]['TEST']['NAME']
113 TEST = decouple_config('TEST', default=False, cast=bool)
114 if TEST:
115     for db_key, _ in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim)):
116         DATABASES[db_key]['TEST'] = {'NAME': DATABASES[db_key]['NAME']}
117 
118 
119 # SECURITY WARNING: keep the secret key used in production secret!
120 SECRET_KEY = decouple_config('SECRET_KEY', default="2gr6ud88x=(p855_5nbj_+7^gw-iz&n7ldqv%94mjaecl+b9=4")
121 
122 # SECURITY WARNING: don't run with debug turned on in production!
123 DEBUG = decouple_config('DEBUG', default=False, cast=bool)
124 
125 ALLOWED_HOSTS = decouple_config('ALLOWED_HOSTS', cast=Csv(), default=".localhost, 127.0.0.1, [::1]")
126 
127 # Password validation
128 # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
129 
130 AUTH_PASSWORD_VALIDATORS = [
131     {
132         "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
133     },
134     {
135         "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
136     },
137     {
138         "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
139     },
140     {
141         "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
142     },
143 ]
144 
145 # Internationalization
146 # https://docs.djangoproject.com/en/3.1/topics/i18n/
147 
148 LANGUAGE_CODE = "en-us"
149 
150 TIME_ZONE = "UTC"
151 
152 USE_I18N = True
153 
154 USE_L10N = True
155 
156 USE_TZ = True
157 
158 # Static files (CSS, JavaScript, Images)
159 # https://docs.djangoproject.com/en/3.1/howto/static-files/
160 # https://docs.djangoproject.com/en/3.1/ref/contrib/staticfiles/
161 
162 STATIC_URL = "/static/"
163 
164 # When running with DEBUG=False, the webserver needs to serve files from this location
165 # python manage.py collectstatic has to be run to collect all static files into this location
166 # The files need to served in brotli or gzip compressed format
167 STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
168 
169 # Media files (uploaded by the user)
170 DEFAULT_MEDIA_ROOT = os.path.join(BASE_DIR, '.media/')
171 MEDIA_ROOT = decouple_config('MEDIA_ROOT', default=DEFAULT_MEDIA_ROOT)
172 
173 MEDIA_URL = "/media/"
174 
175 # Update Authentication classes, removed BasicAuthentication
176 # Defaults: https://www.django-rest-framework.org/api-guide/settings/
177 REST_FRAMEWORK = {
178     'DEFAULT_AUTHENTICATION_CLASSES': [
179         'rest_framework.authentication.TokenAuthentication',
180         'rest_framework.authentication.SessionAuthentication'
181     ],
182     'DEFAULT_PERMISSION_CLASSES': [
183         'rest_framework.permissions.IsAuthenticated',
184     ],
185     'DEFAULT_PARSER_CLASSES': [
186         'rest_framework.parsers.JSONParser',
187     ],
188     'DEFAULT_FILTER_BACKENDS': (
189         'django_filters.rest_framework.DjangoFilterBackend',
190         'rest_framework.filters.OrderingFilter',
191     ),
192     'TEST_REQUEST_DEFAULT_FORMAT': 'json',
193     'EXCEPTION_HANDLER':
194         'mathesar.exception_handlers.mathesar_exception_handler',
195     'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema'
196 }
197 SPECTACULAR_SETTINGS = {
198     'TITLE': 'Mathesar API',
199     'DESCRIPTION': '',
200     'VERSION': '1.0.0',
201     'SERVE_INCLUDE_SCHEMA': False,
202     'PREPROCESSING_HOOKS': ['config.settings.openapi.custom_preprocessing_hook'],
203     'POSTPROCESSING_HOOKS': [
204         'config.settings.openapi.remove_url_prefix_hook',
205     ],
206     # OTHER SETTINGS
207 }
208 FRIENDLY_ERRORS = {
209     'FIELD_ERRORS': {
210         # By default drf-friendly-errors does contain error codes for ListSerializer type
211         'ListSerializer': {
212             'required': 2007,
213             'null': 2027,
214             'invalid_choice': 2083,
215             'not_a_list': 2123,
216             'empty': 2093
217         },
218         'PermittedPkRelatedField': {
219             'required': 2007,
220             'null': 2027,
221             'does_not_exist': 2151,
222             'incorrect_type': 2161
223         },
224         'PermittedSlugRelatedField': {
225             'required': 2007, 'invalid': 2002, 'null': 2027,
226             'does_not_exist': 2151, 'incorrect_type': 2161
227         },
228     },
229     'EXCEPTION_DICT': {
230         'Http404': 4005
231     }
232 }
233 # Mathesar settings
234 MATHESAR_MODE = decouple_config('MODE', default='PRODUCTION')
235 MATHESAR_UI_BUILD_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/mathesar/')
236 MATHESAR_MANIFEST_LOCATION = os.path.join(MATHESAR_UI_BUILD_LOCATION, 'manifest.json')
237 MATHESAR_CLIENT_DEV_URL = decouple_config(
238     'MATHESAR_CLIENT_DEV_URL',
239     default='http://localhost:3000'
240 )
241 MATHESAR_UI_SOURCE_LOCATION = os.path.join(BASE_DIR, 'mathesar_ui/')
242 MATHESAR_CAPTURE_UNHANDLED_EXCEPTION = decouple_config('CAPTURE_UNHANDLED_EXCEPTION', default=False)
243 MATHESAR_STATIC_NON_CODE_FILES_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/non-code/')
244 
245 # UI source files have to be served by Django in order for static assets to be included during dev mode
246 # https://vitejs.dev/guide/assets.html
247 # https://vitejs.dev/guide/backend-integration.html
248 STATICFILES_DIRS = [MATHESAR_UI_SOURCE_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION] if MATHESAR_MODE == 'DEVELOPMENT' else [MATHESAR_UI_BUILD_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION]
249 STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
250 
251 # Accounts
252 AUTH_USER_MODEL = 'mathesar.User'
253 LOGIN_URL = '/auth/login/'
254 LOGIN_REDIRECT_URL = '/'
255 LOGOUT_REDIRECT_URL = LOGIN_URL
256 DRF_ACCESS_POLICY = {
257     'reusable_conditions': ['mathesar.api.permission_conditions']
258 }
259 # List of Template names that contains additional script tags to be added to the base template
260 BASE_TEMPLATE_ADDITIONAL_SCRIPT_TEMPLATES = []
261 
262 # i18n
263 LANGUAGES = [
264     ('en', gettext_lazy('English')),
265     ('ja', gettext_lazy('Japanese')),
266 ]
267 LOCALE_PATHS = [
268     'translations'
269 ]
270 LANGUAGE_COOKIE_NAME = 'display_language'
271 SALT_KEY = SECRET_KEY
272
```

Path: `config/settings/production.py`
Content:
```
1 from config.settings.common_settings import * # noqa
2 
3 # Override default settings
4 
5 
6 # Use a local.py module for settings that shouldn't be version tracked
7 try:
8     from .local import * # noqa 
9 except ImportError:
10     pass
11
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/config/settings/common_settings.py b/config/settings/common_settings.py
--- a/config/settings/common_settings.py
+++ b/config/settings/common_settings.py
@@ -94,10 +94,21 @@
 # See pipe_delim above for why we use pipes as delimiters
 DATABASES = {
     db_key: db_url(url_string)
-    for db_key, url_string in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim))
+    for db_key, url_string in decouple_config('MATHESAR_DATABASES', default='', cast=Csv(pipe_delim))
 }
 
-DATABASES[decouple_config('DJANGO_DATABASE_KEY', default="default")] = decouple_config('DJANGO_DATABASE_URL', cast=db_url, default='sqlite:///db.sqlite3')
+# POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST & POSTGRES_PORT are required env variables for forming a pg connection string for the django database
+# lack of any one of these will result in the internal django database to be sqlite.
+POSTGRES_DB = decouple_config('POSTGRES_DB', default=None)
+POSTGRES_USER = decouple_config('POSTGRES_USER', default=None)
+POSTGRES_PASSWORD = decouple_config('POSTGRES_PASSWORD', default=None)
+POSTGRES_HOST = decouple_config('POSTGRES_HOST', default=None)
+POSTGRES_PORT = decouple_config('POSTGRES_PORT', default=None)
+
+if POSTGRES_DB and POSTGRES_USER and POSTGRES_PASSWORD and POSTGRES_HOST and POSTGRES_PORT:
+    DATABASES['default'] = db_url(f'postgres://{POSTGRES_USER}:{POSTGRES_PASSWORD}@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DB}')
+else:
+    DATABASES['default'] = db_url('sqlite:///db.sqlite3')
 
 for db_key, db_dict in DATABASES.items():
     # Engine should be '.postgresql' or '.postgresql_psycopg2' for all db(s),
diff --git a/config/settings/production.py b/config/settings/production.py
--- a/config/settings/production.py
+++ b/config/settings/production.py
@@ -1,8 +1,8 @@
 from config.settings.common_settings import * # noqa
 
 # Override default settings
-
-
+DEBUG = False
+MATHESAR_MODE = 'PRODUCTION'
 # Use a local.py module for settings that shouldn't be version tracked
 try:
     from .local import * # noqa

{"golden_diff": "diff --git a/config/settings/common_settings.py b/config/settings/common_settings.py\n--- a/config/settings/common_settings.py\n+++ b/config/settings/common_settings.py\n@@ -94,10 +94,21 @@\n # See pipe_delim above for why we use pipes as delimiters\n DATABASES = {\n     db_key: db_url(url_string)\n-    for db_key, url_string in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim))\n+    for db_key, url_string in decouple_config('MATHESAR_DATABASES', default='', cast=Csv(pipe_delim))\n }\n \n-DATABASES[decouple_config('DJANGO_DATABASE_KEY', default=\"default\")] = decouple_config('DJANGO_DATABASE_URL', cast=db_url, default='sqlite:///db.sqlite3')\n+# POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST & POSTGRES_PORT are required env variables for forming a pg connection string for the django database\n+# lack of any one of these will result in the internal django database to be sqlite.\n+POSTGRES_DB = decouple_config('POSTGRES_DB', default=None)\n+POSTGRES_USER = decouple_config('POSTGRES_USER', default=None)\n+POSTGRES_PASSWORD = decouple_config('POSTGRES_PASSWORD', default=None)\n+POSTGRES_HOST = decouple_config('POSTGRES_HOST', default=None)\n+POSTGRES_PORT = decouple_config('POSTGRES_PORT', default=None)\n+\n+if POSTGRES_DB and POSTGRES_USER and POSTGRES_PASSWORD and POSTGRES_HOST and POSTGRES_PORT:\n+    DATABASES['default'] = db_url(f'postgres://{POSTGRES_USER}:{POSTGRES_PASSWORD}@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DB}')\n+else:\n+    DATABASES['default'] = db_url('sqlite:///db.sqlite3')\n \n for db_key, db_dict in DATABASES.items():\n     # Engine should be '.postgresql' or '.postgresql_psycopg2' for all db(s),\ndiff --git a/config/settings/production.py b/config/settings/production.py\n--- a/config/settings/production.py\n+++ b/config/settings/production.py\n@@ -1,8 +1,8 @@\n from config.settings.common_settings import * # noqa\n \n # Override default settings\n-\n-\n+DEBUG = False\n+MATHESAR_MODE = 'PRODUCTION'\n # Use a local.py module for settings that shouldn't be version tracked\n try:\n     from .local import * # noqa\n", "issue": "Make the docker compose file self documenting\n### It should be made clear in the docker compose file:\r\n- The prerequisites required to run the file\r\n- How to actually run the file\r\n- The purpose for each of the environment variables used by different containers\r\n- Their recommended/suggested/default values\r\n\r\n### Goals:\r\n- The need of referring to our docs for this installation method by the user should be eliminated upon resolving this issue.   \r\n- The need of user to add variables in the `.env` file should be removed and instead these variables should be customizable in the compose file itself.\r\n\r\n### Nice to haves:\r\n- Make possible mounting folders as volumes to increase the visibility of the data being stored on user device. This is also useful if the data is being used by some other service on the host device. \r\n- Consider removing watchtower and push user to update manually instead.\r\n\r\n### Additional context\r\n<!-- Add any other context or screenshots about the feature request here.-->\r\nRelated to #3166 \n", "before_files": [{"content": "\"\"\"\nBase settings to build other settings files upon.\n\nGenerated by 'django-admin startproject' using Django 3.1.7.\n\nFor more information on this file, see\nhttps://docs.djangoproject.com/en/3.1/topics/settings/\n\nFor the full list of settings and their values, see\nhttps://docs.djangoproject.com/en/3.1/ref/settings/\n\"\"\"\n\nimport os\nfrom pathlib import Path\n\nfrom decouple import Csv, config as decouple_config\nfrom dj_database_url import parse as db_url\nfrom django.utils.translation import gettext_lazy\n\n\n# We use a 'tuple' with pipes as delimiters as decople naively splits the global\n# variables on commas when casting to Csv()\ndef pipe_delim(pipe_string):\n    # Remove opening and closing brackets\n    pipe_string = pipe_string[1:-1]\n    # Split on pipe delim\n    return pipe_string.split(\"|\")\n\n\n# Build paths inside the project like this: BASE_DIR / 'subdir'.\nBASE_DIR = Path(__file__).resolve().parent.parent.parent\n\n# Application definition\n\nINSTALLED_APPS = [\n    \"django.contrib.admin\",\n    \"django.contrib.auth\",\n    \"django.contrib.contenttypes\",\n    \"django.contrib.sessions\",\n    \"django.contrib.messages\",\n    \"whitenoise.runserver_nostatic\",\n    \"django.contrib.staticfiles\",\n    \"rest_framework\",\n    \"django_filters\",\n    \"django_property_filter\",\n    \"drf_spectacular\",\n    \"mathesar\",\n]\n\nMIDDLEWARE = [\n    \"django.middleware.security.SecurityMiddleware\",\n    \"whitenoise.middleware.WhiteNoiseMiddleware\",\n    \"django.contrib.sessions.middleware.SessionMiddleware\",\n    \"django.middleware.locale.LocaleMiddleware\",\n    \"django.middleware.common.CommonMiddleware\",\n    \"django.middleware.csrf.CsrfViewMiddleware\",\n    \"django.contrib.auth.middleware.AuthenticationMiddleware\",\n    \"django.contrib.messages.middleware.MessageMiddleware\",\n    \"django.middleware.clickjacking.XFrameOptionsMiddleware\",\n    \"mathesar.middleware.CursorClosedHandlerMiddleware\",\n    \"mathesar.middleware.PasswordChangeNeededMiddleware\",\n    'django_userforeignkey.middleware.UserForeignKeyMiddleware',\n    'django_request_cache.middleware.RequestCacheMiddleware',\n]\n\nROOT_URLCONF = \"config.urls\"\n\nTEMPLATES = [\n    {\n        \"BACKEND\": \"django.template.backends.django.DjangoTemplates\",\n        \"DIRS\": [],\n        \"APP_DIRS\": True,\n        \"OPTIONS\": {\n            \"context_processors\": [\n                \"config.context_processors.frontend_settings\",\n                \"django.template.context_processors.debug\",\n                \"django.template.context_processors.request\",\n                \"django.contrib.auth.context_processors.auth\",\n                \"django.contrib.messages.context_processors.messages\",\n                \"mathesar.template_context_processors.base_template_extensions.script_extension_templates\"\n            ],\n        },\n    },\n]\n\nWSGI_APPLICATION = \"config.wsgi.application\"\n\n# Database\n# https://docs.djangoproject.com/en/3.1/ref/settings/#databases\n\n# TODO: Add to documentation that database keys should not be than 128 characters.\n\n# MATHESAR_DATABASES should be of the form '({db_name}|{db_url}), ({db_name}|{db_url})'\n# See pipe_delim above for why we use pipes as delimiters\nDATABASES = {\n    db_key: db_url(url_string)\n    for db_key, url_string in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim))\n}\n\nDATABASES[decouple_config('DJANGO_DATABASE_KEY', default=\"default\")] = decouple_config('DJANGO_DATABASE_URL', cast=db_url, default='sqlite:///db.sqlite3')\n\nfor db_key, db_dict in DATABASES.items():\n    # Engine should be '.postgresql' or '.postgresql_psycopg2' for all db(s),\n    # however for the internal 'default' db 'sqlite3' can be used.\n    if not db_dict['ENGINE'].startswith('django.db.backends.postgresql') and db_key != 'default':\n        raise ValueError(\n            f\"{db_key} is not a PostgreSQL database. \"\n            f\"{db_dict['ENGINE']} found for {db_key}'s engine.\"\n        )\n\n# pytest-django will create a new database named 'test_{DATABASES[table_db]['NAME']}'\n# and use it for our API tests if we don't specify DATABASES[table_db]['TEST']['NAME']\nTEST = decouple_config('TEST', default=False, cast=bool)\nif TEST:\n    for db_key, _ in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim)):\n        DATABASES[db_key]['TEST'] = {'NAME': DATABASES[db_key]['NAME']}\n\n\n# SECURITY WARNING: keep the secret key used in production secret!\nSECRET_KEY = decouple_config('SECRET_KEY', default=\"2gr6ud88x=(p855_5nbj_+7^gw-iz&n7ldqv%94mjaecl+b9=4\")\n\n# SECURITY WARNING: don't run with debug turned on in production!\nDEBUG = decouple_config('DEBUG', default=False, cast=bool)\n\nALLOWED_HOSTS = decouple_config('ALLOWED_HOSTS', cast=Csv(), default=\".localhost, 127.0.0.1, [::1]\")\n\n# Password validation\n# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators\n\nAUTH_PASSWORD_VALIDATORS = [\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.UserAttributeSimilarityValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.MinimumLengthValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.CommonPasswordValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.NumericPasswordValidator\",\n    },\n]\n\n# Internationalization\n# https://docs.djangoproject.com/en/3.1/topics/i18n/\n\nLANGUAGE_CODE = \"en-us\"\n\nTIME_ZONE = \"UTC\"\n\nUSE_I18N = True\n\nUSE_L10N = True\n\nUSE_TZ = True\n\n# Static files (CSS, JavaScript, Images)\n# https://docs.djangoproject.com/en/3.1/howto/static-files/\n# https://docs.djangoproject.com/en/3.1/ref/contrib/staticfiles/\n\nSTATIC_URL = \"/static/\"\n\n# When running with DEBUG=False, the webserver needs to serve files from this location\n# python manage.py collectstatic has to be run to collect all static files into this location\n# The files need to served in brotli or gzip compressed format\nSTATIC_ROOT = os.path.join(BASE_DIR, 'static/')\n\n# Media files (uploaded by the user)\nDEFAULT_MEDIA_ROOT = os.path.join(BASE_DIR, '.media/')\nMEDIA_ROOT = decouple_config('MEDIA_ROOT', default=DEFAULT_MEDIA_ROOT)\n\nMEDIA_URL = \"/media/\"\n\n# Update Authentication classes, removed BasicAuthentication\n# Defaults: https://www.django-rest-framework.org/api-guide/settings/\nREST_FRAMEWORK = {\n    'DEFAULT_AUTHENTICATION_CLASSES': [\n        'rest_framework.authentication.TokenAuthentication',\n        'rest_framework.authentication.SessionAuthentication'\n    ],\n    'DEFAULT_PERMISSION_CLASSES': [\n        'rest_framework.permissions.IsAuthenticated',\n    ],\n    'DEFAULT_PARSER_CLASSES': [\n        'rest_framework.parsers.JSONParser',\n    ],\n    'DEFAULT_FILTER_BACKENDS': (\n        'django_filters.rest_framework.DjangoFilterBackend',\n        'rest_framework.filters.OrderingFilter',\n    ),\n    'TEST_REQUEST_DEFAULT_FORMAT': 'json',\n    'EXCEPTION_HANDLER':\n        'mathesar.exception_handlers.mathesar_exception_handler',\n    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema'\n}\nSPECTACULAR_SETTINGS = {\n    'TITLE': 'Mathesar API',\n    'DESCRIPTION': '',\n    'VERSION': '1.0.0',\n    'SERVE_INCLUDE_SCHEMA': False,\n    'PREPROCESSING_HOOKS': ['config.settings.openapi.custom_preprocessing_hook'],\n    'POSTPROCESSING_HOOKS': [\n        'config.settings.openapi.remove_url_prefix_hook',\n    ],\n    # OTHER SETTINGS\n}\nFRIENDLY_ERRORS = {\n    'FIELD_ERRORS': {\n        # By default drf-friendly-errors does contain error codes for ListSerializer type\n        'ListSerializer': {\n            'required': 2007,\n            'null': 2027,\n            'invalid_choice': 2083,\n            'not_a_list': 2123,\n            'empty': 2093\n        },\n        'PermittedPkRelatedField': {\n            'required': 2007,\n            'null': 2027,\n            'does_not_exist': 2151,\n            'incorrect_type': 2161\n        },\n        'PermittedSlugRelatedField': {\n            'required': 2007, 'invalid': 2002, 'null': 2027,\n            'does_not_exist': 2151, 'incorrect_type': 2161\n        },\n    },\n    'EXCEPTION_DICT': {\n        'Http404': 4005\n    }\n}\n# Mathesar settings\nMATHESAR_MODE = decouple_config('MODE', default='PRODUCTION')\nMATHESAR_UI_BUILD_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/mathesar/')\nMATHESAR_MANIFEST_LOCATION = os.path.join(MATHESAR_UI_BUILD_LOCATION, 'manifest.json')\nMATHESAR_CLIENT_DEV_URL = decouple_config(\n    'MATHESAR_CLIENT_DEV_URL',\n    default='http://localhost:3000'\n)\nMATHESAR_UI_SOURCE_LOCATION = os.path.join(BASE_DIR, 'mathesar_ui/')\nMATHESAR_CAPTURE_UNHANDLED_EXCEPTION = decouple_config('CAPTURE_UNHANDLED_EXCEPTION', default=False)\nMATHESAR_STATIC_NON_CODE_FILES_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/non-code/')\n\n# UI source files have to be served by Django in order for static assets to be included during dev mode\n# https://vitejs.dev/guide/assets.html\n# https://vitejs.dev/guide/backend-integration.html\nSTATICFILES_DIRS = [MATHESAR_UI_SOURCE_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION] if MATHESAR_MODE == 'DEVELOPMENT' else [MATHESAR_UI_BUILD_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION]\nSTATICFILES_STORAGE = \"whitenoise.storage.CompressedManifestStaticFilesStorage\"\n\n# Accounts\nAUTH_USER_MODEL = 'mathesar.User'\nLOGIN_URL = '/auth/login/'\nLOGIN_REDIRECT_URL = '/'\nLOGOUT_REDIRECT_URL = LOGIN_URL\nDRF_ACCESS_POLICY = {\n    'reusable_conditions': ['mathesar.api.permission_conditions']\n}\n# List of Template names that contains additional script tags to be added to the base template\nBASE_TEMPLATE_ADDITIONAL_SCRIPT_TEMPLATES = []\n\n# i18n\nLANGUAGES = [\n    ('en', gettext_lazy('English')),\n    ('ja', gettext_lazy('Japanese')),\n]\nLOCALE_PATHS = [\n    'translations'\n]\nLANGUAGE_COOKIE_NAME = 'display_language'\nSALT_KEY = SECRET_KEY\n", "path": "config/settings/common_settings.py"}, {"content": "from config.settings.common_settings import * # noqa\n\n# Override default settings\n\n\n# Use a local.py module for settings that shouldn't be version tracked\ntry:\n    from .local import * # noqa \nexcept ImportError:\n    pass\n", "path": "config/settings/production.py"}], "after_files": [{"content": "\"\"\"\nBase settings to build other settings files upon.\n\nGenerated by 'django-admin startproject' using Django 3.1.7.\n\nFor more information on this file, see\nhttps://docs.djangoproject.com/en/3.1/topics/settings/\n\nFor the full list of settings and their values, see\nhttps://docs.djangoproject.com/en/3.1/ref/settings/\n\"\"\"\n\nimport os\nfrom pathlib import Path\n\nfrom decouple import Csv, config as decouple_config\nfrom dj_database_url import parse as db_url\nfrom django.utils.translation import gettext_lazy\n\n\n# We use a 'tuple' with pipes as delimiters as decople naively splits the global\n# variables on commas when casting to Csv()\ndef pipe_delim(pipe_string):\n    # Remove opening and closing brackets\n    pipe_string = pipe_string[1:-1]\n    # Split on pipe delim\n    return pipe_string.split(\"|\")\n\n\n# Build paths inside the project like this: BASE_DIR / 'subdir'.\nBASE_DIR = Path(__file__).resolve().parent.parent.parent\n\n# Application definition\n\nINSTALLED_APPS = [\n    \"django.contrib.admin\",\n    \"django.contrib.auth\",\n    \"django.contrib.contenttypes\",\n    \"django.contrib.sessions\",\n    \"django.contrib.messages\",\n    \"whitenoise.runserver_nostatic\",\n    \"django.contrib.staticfiles\",\n    \"rest_framework\",\n    \"django_filters\",\n    \"django_property_filter\",\n    \"drf_spectacular\",\n    \"mathesar\",\n]\n\nMIDDLEWARE = [\n    \"django.middleware.security.SecurityMiddleware\",\n    \"whitenoise.middleware.WhiteNoiseMiddleware\",\n    \"django.contrib.sessions.middleware.SessionMiddleware\",\n    \"django.middleware.locale.LocaleMiddleware\",\n    \"django.middleware.common.CommonMiddleware\",\n    \"django.middleware.csrf.CsrfViewMiddleware\",\n    \"django.contrib.auth.middleware.AuthenticationMiddleware\",\n    \"django.contrib.messages.middleware.MessageMiddleware\",\n    \"django.middleware.clickjacking.XFrameOptionsMiddleware\",\n    \"mathesar.middleware.CursorClosedHandlerMiddleware\",\n    \"mathesar.middleware.PasswordChangeNeededMiddleware\",\n    'django_userforeignkey.middleware.UserForeignKeyMiddleware',\n    'django_request_cache.middleware.RequestCacheMiddleware',\n]\n\nROOT_URLCONF = \"config.urls\"\n\nTEMPLATES = [\n    {\n        \"BACKEND\": \"django.template.backends.django.DjangoTemplates\",\n        \"DIRS\": [],\n        \"APP_DIRS\": True,\n        \"OPTIONS\": {\n            \"context_processors\": [\n                \"config.context_processors.frontend_settings\",\n                \"django.template.context_processors.debug\",\n                \"django.template.context_processors.request\",\n                \"django.contrib.auth.context_processors.auth\",\n                \"django.contrib.messages.context_processors.messages\",\n                \"mathesar.template_context_processors.base_template_extensions.script_extension_templates\"\n            ],\n        },\n    },\n]\n\nWSGI_APPLICATION = \"config.wsgi.application\"\n\n# Database\n# https://docs.djangoproject.com/en/3.1/ref/settings/#databases\n\n# TODO: Add to documentation that database keys should not be than 128 characters.\n\n# MATHESAR_DATABASES should be of the form '({db_name}|{db_url}), ({db_name}|{db_url})'\n# See pipe_delim above for why we use pipes as delimiters\nDATABASES = {\n    db_key: db_url(url_string)\n    for db_key, url_string in decouple_config('MATHESAR_DATABASES', default='', cast=Csv(pipe_delim))\n}\n\n# POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST & POSTGRES_PORT are required env variables for forming a pg connection string for the django database\n# lack of any one of these will result in the internal django database to be sqlite.\nPOSTGRES_DB = decouple_config('POSTGRES_DB', default=None)\nPOSTGRES_USER = decouple_config('POSTGRES_USER', default=None)\nPOSTGRES_PASSWORD = decouple_config('POSTGRES_PASSWORD', default=None)\nPOSTGRES_HOST = decouple_config('POSTGRES_HOST', default=None)\nPOSTGRES_PORT = decouple_config('POSTGRES_PORT', default=None)\n\nif POSTGRES_DB and POSTGRES_USER and POSTGRES_PASSWORD and POSTGRES_HOST and POSTGRES_PORT:\n    DATABASES['default'] = db_url(f'postgres://{POSTGRES_USER}:{POSTGRES_PASSWORD}@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DB}')\nelse:\n    DATABASES['default'] = db_url('sqlite:///db.sqlite3')\n\nfor db_key, db_dict in DATABASES.items():\n    # Engine should be '.postgresql' or '.postgresql_psycopg2' for all db(s),\n    # however for the internal 'default' db 'sqlite3' can be used.\n    if not db_dict['ENGINE'].startswith('django.db.backends.postgresql') and db_key != 'default':\n        raise ValueError(\n            f\"{db_key} is not a PostgreSQL database. \"\n            f\"{db_dict['ENGINE']} found for {db_key}'s engine.\"\n        )\n\n# pytest-django will create a new database named 'test_{DATABASES[table_db]['NAME']}'\n# and use it for our API tests if we don't specify DATABASES[table_db]['TEST']['NAME']\nTEST = decouple_config('TEST', default=False, cast=bool)\nif TEST:\n    for db_key, _ in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim)):\n        DATABASES[db_key]['TEST'] = {'NAME': DATABASES[db_key]['NAME']}\n\n\n# SECURITY WARNING: keep the secret key used in production secret!\nSECRET_KEY = decouple_config('SECRET_KEY', default=\"2gr6ud88x=(p855_5nbj_+7^gw-iz&n7ldqv%94mjaecl+b9=4\")\n\n# SECURITY WARNING: don't run with debug turned on in production!\nDEBUG = decouple_config('DEBUG', default=False, cast=bool)\n\nALLOWED_HOSTS = decouple_config('ALLOWED_HOSTS', cast=Csv(), default=\".localhost, 127.0.0.1, [::1]\")\n\n# Password validation\n# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators\n\nAUTH_PASSWORD_VALIDATORS = [\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.UserAttributeSimilarityValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.MinimumLengthValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.CommonPasswordValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.NumericPasswordValidator\",\n    },\n]\n\n# Internationalization\n# https://docs.djangoproject.com/en/3.1/topics/i18n/\n\nLANGUAGE_CODE = \"en-us\"\n\nTIME_ZONE = \"UTC\"\n\nUSE_I18N = True\n\nUSE_L10N = True\n\nUSE_TZ = True\n\n# Static files (CSS, JavaScript, Images)\n# https://docs.djangoproject.com/en/3.1/howto/static-files/\n# https://docs.djangoproject.com/en/3.1/ref/contrib/staticfiles/\n\nSTATIC_URL = \"/static/\"\n\n# When running with DEBUG=False, the webserver needs to serve files from this location\n# python manage.py collectstatic has to be run to collect all static files into this location\n# The files need to served in brotli or gzip compressed format\nSTATIC_ROOT = os.path.join(BASE_DIR, 'static/')\n\n# Media files (uploaded by the user)\nDEFAULT_MEDIA_ROOT = os.path.join(BASE_DIR, '.media/')\nMEDIA_ROOT = decouple_config('MEDIA_ROOT', default=DEFAULT_MEDIA_ROOT)\n\nMEDIA_URL = \"/media/\"\n\n# Update Authentication classes, removed BasicAuthentication\n# Defaults: https://www.django-rest-framework.org/api-guide/settings/\nREST_FRAMEWORK = {\n    'DEFAULT_AUTHENTICATION_CLASSES': [\n        'rest_framework.authentication.TokenAuthentication',\n        'rest_framework.authentication.SessionAuthentication'\n    ],\n    'DEFAULT_PERMISSION_CLASSES': [\n        'rest_framework.permissions.IsAuthenticated',\n    ],\n    'DEFAULT_PARSER_CLASSES': [\n        'rest_framework.parsers.JSONParser',\n    ],\n    'DEFAULT_FILTER_BACKENDS': (\n        'django_filters.rest_framework.DjangoFilterBackend',\n        'rest_framework.filters.OrderingFilter',\n    ),\n    'TEST_REQUEST_DEFAULT_FORMAT': 'json',\n    'EXCEPTION_HANDLER':\n        'mathesar.exception_handlers.mathesar_exception_handler',\n    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema'\n}\nSPECTACULAR_SETTINGS = {\n    'TITLE': 'Mathesar API',\n    'DESCRIPTION': '',\n    'VERSION': '1.0.0',\n    'SERVE_INCLUDE_SCHEMA': False,\n    'PREPROCESSING_HOOKS': ['config.settings.openapi.custom_preprocessing_hook'],\n    'POSTPROCESSING_HOOKS': [\n        'config.settings.openapi.remove_url_prefix_hook',\n    ],\n    # OTHER SETTINGS\n}\nFRIENDLY_ERRORS = {\n    'FIELD_ERRORS': {\n        # By default drf-friendly-errors does contain error codes for ListSerializer type\n        'ListSerializer': {\n            'required': 2007,\n            'null': 2027,\n            'invalid_choice': 2083,\n            'not_a_list': 2123,\n            'empty': 2093\n        },\n        'PermittedPkRelatedField': {\n            'required': 2007,\n            'null': 2027,\n            'does_not_exist': 2151,\n            'incorrect_type': 2161\n        },\n        'PermittedSlugRelatedField': {\n            'required': 2007, 'invalid': 2002, 'null': 2027,\n            'does_not_exist': 2151, 'incorrect_type': 2161\n        },\n    },\n    'EXCEPTION_DICT': {\n        'Http404': 4005\n    }\n}\n# Mathesar settings\nMATHESAR_MODE = decouple_config('MODE', default='PRODUCTION')\nMATHESAR_UI_BUILD_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/mathesar/')\nMATHESAR_MANIFEST_LOCATION = os.path.join(MATHESAR_UI_BUILD_LOCATION, 'manifest.json')\nMATHESAR_CLIENT_DEV_URL = decouple_config(\n    'MATHESAR_CLIENT_DEV_URL',\n    default='http://localhost:3000'\n)\nMATHESAR_UI_SOURCE_LOCATION = os.path.join(BASE_DIR, 'mathesar_ui/')\nMATHESAR_CAPTURE_UNHANDLED_EXCEPTION = decouple_config('CAPTURE_UNHANDLED_EXCEPTION', default=False)\nMATHESAR_STATIC_NON_CODE_FILES_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/non-code/')\n\n# UI source files have to be served by Django in order for static assets to be included during dev mode\n# https://vitejs.dev/guide/assets.html\n# https://vitejs.dev/guide/backend-integration.html\nSTATICFILES_DIRS = [MATHESAR_UI_SOURCE_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION] if MATHESAR_MODE == 'DEVELOPMENT' else [MATHESAR_UI_BUILD_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION]\nSTATICFILES_STORAGE = \"whitenoise.storage.CompressedManifestStaticFilesStorage\"\n\n# Accounts\nAUTH_USER_MODEL = 'mathesar.User'\nLOGIN_URL = '/auth/login/'\nLOGIN_REDIRECT_URL = '/'\nLOGOUT_REDIRECT_URL = LOGIN_URL\nDRF_ACCESS_POLICY = {\n    'reusable_conditions': ['mathesar.api.permission_conditions']\n}\n# List of Template names that contains additional script tags to be added to the base template\nBASE_TEMPLATE_ADDITIONAL_SCRIPT_TEMPLATES = []\n\n# i18n\nLANGUAGES = [\n    ('en', gettext_lazy('English')),\n    ('ja', gettext_lazy('Japanese')),\n]\nLOCALE_PATHS = [\n    'translations'\n]\nLANGUAGE_COOKIE_NAME = 'display_language'\nSALT_KEY = SECRET_KEY\n", "path": "config/settings/common_settings.py"}, {"content": "from config.settings.common_settings import * # noqa\n\n# Override default settings\nDEBUG = False\nMATHESAR_MODE = 'PRODUCTION'\n# Use a local.py module for settings that shouldn't be version tracked\ntry:\n    from .local import * # noqa \nexcept ImportError:\n    pass\n", "path": "config/settings/production.py"}]}