We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Table, Database, & Schema APIs should support sorting by ID & name
## Problem
<!-- Please provide a clear and concise description of the problem that this feature request is designed to solve.-->
The table, database, and schema APIs don't currently support sorting results.

## Proposed solution
<!-- A clear and concise description of your proposed solution or feature. -->
All three APIs should support sorting by ID and name.

## Additional context
<!-- Add any other context or screenshots about the feature request here.-->
We can use `django-filter` / `django-property-filter` for this.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mathesar/api/filters.py`
Content:
```
1 from django_filters import BooleanFilter, DateTimeFromToRangeFilter
2 from django_property_filter import PropertyFilterSet, PropertyBaseInFilter, PropertyCharFilter
3 
4 from mathesar.database.types import MathesarTypeIdentifier
5 from mathesar.models import Schema, Table, Database
6 
7 FILTER_OPTIONS_BY_TYPE_IDENTIFIER = {
8     MathesarTypeIdentifier.BOOLEAN.value:
9     {
10         "db_type": "BOOLEAN",
11         "options": [{
12             "op": "eq",
13             "value": {
14                 "allowed_types": ["BOOLEAN"],
15             }
16         }, {
17             "op": "is_null",
18             "value": "null",
19         }]
20     }
21 }
22 
23 
24 class CharInFilter(PropertyBaseInFilter, PropertyCharFilter):
25     pass
26 
27 
28 class SchemaFilter(PropertyFilterSet):
29     database = CharInFilter(field_name='database__name', lookup_expr='in')
30     name = CharInFilter(field_name='name', lookup_expr='in')
31 
32     class Meta:
33         model = Schema
34         fields = ['name']
35 
36 
37 class TableFilter(PropertyFilterSet):
38     name = CharInFilter(field_name='name', lookup_expr='in')
39     created = DateTimeFromToRangeFilter(field_name='created_at')
40     updated = DateTimeFromToRangeFilter(field_name='updated_at')
41     not_imported = BooleanFilter(lookup_expr="isnull", field_name='import_verified')
42 
43     class Meta:
44         model = Table
45         fields = ['name', 'schema', 'created_at', 'updated_at', 'import_verified']
46 
47 
48 class DatabaseFilter(PropertyFilterSet):
49     class Meta:
50         model = Database
51         fields = ['deleted']
52
```

Path: `config/settings.py`
Content:
```
1 """
2 Django settings for config project.
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 
19 
20 # We use a 'tuple' with pipes as delimiters as decople naively splits the global
21 # variables on commas when casting to Csv()
22 def pipe_delim(pipe_string):
23     # Remove opening and closing brackets
24     pipe_string = pipe_string[1:-1]
25     # Split on pipe delim
26     return pipe_string.split("|")
27 
28 
29 # Build paths inside the project like this: BASE_DIR / 'subdir'.
30 BASE_DIR = Path(__file__).resolve().parent.parent
31 
32 # Application definition
33 
34 INSTALLED_APPS = [
35     "django.contrib.admin",
36     "django.contrib.auth",
37     "django.contrib.contenttypes",
38     "django.contrib.sessions",
39     "django.contrib.messages",
40     "django.contrib.staticfiles",
41     "rest_framework",
42     "django_filters",
43     "django_property_filter",
44     "mathesar",
45 ]
46 
47 MIDDLEWARE = [
48     "django.middleware.security.SecurityMiddleware",
49     "django.contrib.sessions.middleware.SessionMiddleware",
50     "django.middleware.common.CommonMiddleware",
51     "django.middleware.csrf.CsrfViewMiddleware",
52     "django.contrib.auth.middleware.AuthenticationMiddleware",
53     "django.contrib.messages.middleware.MessageMiddleware",
54     "django.middleware.clickjacking.XFrameOptionsMiddleware",
55 ]
56 
57 ROOT_URLCONF = "config.urls"
58 
59 TEMPLATES = [
60     {
61         "BACKEND": "django.template.backends.django.DjangoTemplates",
62         "DIRS": [],
63         "APP_DIRS": True,
64         "OPTIONS": {
65             "context_processors": [
66                 "config.context_processors.frontend_settings",
67                 "django.template.context_processors.debug",
68                 "django.template.context_processors.request",
69                 "django.contrib.auth.context_processors.auth",
70                 "django.contrib.messages.context_processors.messages",
71             ],
72         },
73     },
74 ]
75 
76 WSGI_APPLICATION = "config.wsgi.application"
77 
78 # Database
79 # https://docs.djangoproject.com/en/3.1/ref/settings/#databases
80 
81 # TODO: Add to documentation that database keys should not be than 128 characters.
82 
83 # MATHESAR_DATABASES should be of the form '({db_name}|{db_url}), ({db_name}|{db_url})'
84 # See pipe_delim above for why we use pipes as delimiters
85 DATABASES = {
86     db_key: db_url(url_string)
87     for db_key, url_string in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim))
88 }
89 DATABASES[decouple_config('DJANGO_DATABASE_KEY')] = decouple_config('DJANGO_DATABASE_URL', cast=db_url)
90 
91 for db_key, db_dict in DATABASES.items():
92     # Engine can be '.postgresql' or '.postgresql_psycopg2'
93     if not db_dict['ENGINE'].startswith('django.db.backends.postgresql'):
94         raise ValueError(
95             f"{db_key} is not a PostgreSQL database. "
96             f"{db_dict['ENGINE']} found for {db_key}'s engine."
97         )
98 
99 
100 # pytest-django will create a new database named 'test_{DATABASES[table_db]['NAME']}'
101 # and use it for our API tests if we don't specify DATABASES[table_db]['TEST']['NAME']
102 if decouple_config('TEST', default=False, cast=bool):
103     for db_key, _ in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim)):
104         DATABASES[db_key]['TEST'] = {'NAME': DATABASES[db_key]['NAME']}
105 
106 
107 # Quick-start development settings - unsuitable for production
108 # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
109 
110 # SECURITY WARNING: keep the secret key used in production secret!
111 SECRET_KEY = decouple_config('SECRET_KEY')
112 
113 # SECURITY WARNING: don't run with debug turned on in production!
114 DEBUG = decouple_config('DEBUG', default=False, cast=bool)
115 
116 ALLOWED_HOSTS = decouple_config('ALLOWED_HOSTS', cast=Csv())
117 
118 # Password validation
119 # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
120 
121 AUTH_PASSWORD_VALIDATORS = [
122     {
123         "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
124     },
125     {
126         "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
127     },
128     {
129         "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
130     },
131     {
132         "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
133     },
134 ]
135 
136 
137 # Internationalization
138 # https://docs.djangoproject.com/en/3.1/topics/i18n/
139 
140 LANGUAGE_CODE = "en-us"
141 
142 TIME_ZONE = "UTC"
143 
144 USE_I18N = True
145 
146 USE_L10N = True
147 
148 USE_TZ = True
149 
150 
151 # Static files (CSS, JavaScript, Images)
152 # https://docs.djangoproject.com/en/3.1/howto/static-files/
153 # https://docs.djangoproject.com/en/3.1/ref/contrib/staticfiles/
154 
155 STATIC_URL = "/static/"
156 
157 # When running with DEBUG=False, the webserver needs to serve files from this location
158 # python manage.py collectstatic has to be run to collect all static files into this location
159 # The files need to served in brotli or gzip compressed format
160 STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
161 
162 # Media files (uploaded by the user)
163 
164 MEDIA_ROOT = os.path.join(BASE_DIR, '.media/')
165 
166 MEDIA_URL = "/media/"
167 
168 # Update Authentication classes, removed BasicAuthentication
169 # Defaults: https://www.django-rest-framework.org/api-guide/settings/
170 REST_FRAMEWORK = {
171     'DEFAULT_AUTHENTICATION_CLASSES': [
172         'rest_framework.authentication.SessionAuthentication'
173     ]
174 }
175 
176 # Mathesar settings
177 MATHESAR_MODE = decouple_config('MODE', default='PRODUCTION')
178 MATHESAR_UI_BUILD_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/mathesar/')
179 MATHESAR_MANIFEST_LOCATION = os.path.join(MATHESAR_UI_BUILD_LOCATION, 'manifest.json')
180 MATHESAR_CLIENT_DEV_URL = 'http://localhost:3000'
181 
182 
183 STATICFILES_DIRS = [MATHESAR_UI_BUILD_LOCATION]
184
```
--- 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.py b/config/settings.py
--- a/config/settings.py
+++ b/config/settings.py
@@ -170,7 +170,11 @@
 REST_FRAMEWORK = {
     'DEFAULT_AUTHENTICATION_CLASSES': [
         'rest_framework.authentication.SessionAuthentication'
-    ]
+    ],
+    'DEFAULT_FILTER_BACKENDS': (
+        'django_filters.rest_framework.DjangoFilterBackend',
+        'rest_framework.filters.OrderingFilter',
+    ),
 }
 
 # Mathesar settings
diff --git a/mathesar/api/filters.py b/mathesar/api/filters.py
--- a/mathesar/api/filters.py
+++ b/mathesar/api/filters.py
@@ -1,5 +1,5 @@
-from django_filters import BooleanFilter, DateTimeFromToRangeFilter
-from django_property_filter import PropertyFilterSet, PropertyBaseInFilter, PropertyCharFilter
+from django_filters import BooleanFilter, DateTimeFromToRangeFilter, OrderingFilter
+from django_property_filter import PropertyFilterSet, PropertyBaseInFilter, PropertyCharFilter, PropertyOrderingFilter
 
 from mathesar.database.types import MathesarTypeIdentifier
 from mathesar.models import Schema, Table, Database
@@ -29,6 +29,14 @@
     database = CharInFilter(field_name='database__name', lookup_expr='in')
     name = CharInFilter(field_name='name', lookup_expr='in')
 
+    sort_by = PropertyOrderingFilter(
+        fields=(
+            ('id', 'id'),
+            ('name', 'name'),
+        ),
+        label="Sort By",
+    )
+
     class Meta:
         model = Schema
         fields = ['name']
@@ -40,12 +48,28 @@
     updated = DateTimeFromToRangeFilter(field_name='updated_at')
     not_imported = BooleanFilter(lookup_expr="isnull", field_name='import_verified')
 
+    sort_by = PropertyOrderingFilter(
+        fields=(
+            ('id', 'id'),
+            ('name', 'name'),
+        ),
+        label="Sort By",
+    )
+
     class Meta:
         model = Table
         fields = ['name', 'schema', 'created_at', 'updated_at', 'import_verified']
 
 
 class DatabaseFilter(PropertyFilterSet):
+    sort_by = OrderingFilter(
+        fields=(
+            ('id', 'id'),
+            ('name', 'name'),
+        ),
+        label="Sort By",
+    )
+
     class Meta:
         model = Database
         fields = ['deleted']

{"golden_diff": "diff --git a/config/settings.py b/config/settings.py\n--- a/config/settings.py\n+++ b/config/settings.py\n@@ -170,7 +170,11 @@\n REST_FRAMEWORK = {\n     'DEFAULT_AUTHENTICATION_CLASSES': [\n         'rest_framework.authentication.SessionAuthentication'\n-    ]\n+    ],\n+    'DEFAULT_FILTER_BACKENDS': (\n+        'django_filters.rest_framework.DjangoFilterBackend',\n+        'rest_framework.filters.OrderingFilter',\n+    ),\n }\n \n # Mathesar settings\ndiff --git a/mathesar/api/filters.py b/mathesar/api/filters.py\n--- a/mathesar/api/filters.py\n+++ b/mathesar/api/filters.py\n@@ -1,5 +1,5 @@\n-from django_filters import BooleanFilter, DateTimeFromToRangeFilter\n-from django_property_filter import PropertyFilterSet, PropertyBaseInFilter, PropertyCharFilter\n+from django_filters import BooleanFilter, DateTimeFromToRangeFilter, OrderingFilter\n+from django_property_filter import PropertyFilterSet, PropertyBaseInFilter, PropertyCharFilter, PropertyOrderingFilter\n \n from mathesar.database.types import MathesarTypeIdentifier\n from mathesar.models import Schema, Table, Database\n@@ -29,6 +29,14 @@\n     database = CharInFilter(field_name='database__name', lookup_expr='in')\n     name = CharInFilter(field_name='name', lookup_expr='in')\n \n+    sort_by = PropertyOrderingFilter(\n+        fields=(\n+            ('id', 'id'),\n+            ('name', 'name'),\n+        ),\n+        label=\"Sort By\",\n+    )\n+\n     class Meta:\n         model = Schema\n         fields = ['name']\n@@ -40,12 +48,28 @@\n     updated = DateTimeFromToRangeFilter(field_name='updated_at')\n     not_imported = BooleanFilter(lookup_expr=\"isnull\", field_name='import_verified')\n \n+    sort_by = PropertyOrderingFilter(\n+        fields=(\n+            ('id', 'id'),\n+            ('name', 'name'),\n+        ),\n+        label=\"Sort By\",\n+    )\n+\n     class Meta:\n         model = Table\n         fields = ['name', 'schema', 'created_at', 'updated_at', 'import_verified']\n \n \n class DatabaseFilter(PropertyFilterSet):\n+    sort_by = OrderingFilter(\n+        fields=(\n+            ('id', 'id'),\n+            ('name', 'name'),\n+        ),\n+        label=\"Sort By\",\n+    )\n+\n     class Meta:\n         model = Database\n         fields = ['deleted']\n", "issue": "Table, Database, & Schema APIs should support sorting by ID & name\n## Problem\r\n<!-- Please provide a clear and concise description of the problem that this feature request is designed to solve.-->\r\nThe table, database, and schema APIs don't currently support sorting results.\r\n\r\n## Proposed solution\r\n<!-- A clear and concise description of your proposed solution or feature. -->\r\nAll three APIs should support sorting by ID and name.\r\n\r\n## Additional context\r\n<!-- Add any other context or screenshots about the feature request here.-->\r\nWe can use `django-filter` / `django-property-filter` for this.\n", "before_files": [{"content": "from django_filters import BooleanFilter, DateTimeFromToRangeFilter\nfrom django_property_filter import PropertyFilterSet, PropertyBaseInFilter, PropertyCharFilter\n\nfrom mathesar.database.types import MathesarTypeIdentifier\nfrom mathesar.models import Schema, Table, Database\n\nFILTER_OPTIONS_BY_TYPE_IDENTIFIER = {\n    MathesarTypeIdentifier.BOOLEAN.value:\n    {\n        \"db_type\": \"BOOLEAN\",\n        \"options\": [{\n            \"op\": \"eq\",\n            \"value\": {\n                \"allowed_types\": [\"BOOLEAN\"],\n            }\n        }, {\n            \"op\": \"is_null\",\n            \"value\": \"null\",\n        }]\n    }\n}\n\n\nclass CharInFilter(PropertyBaseInFilter, PropertyCharFilter):\n    pass\n\n\nclass SchemaFilter(PropertyFilterSet):\n    database = CharInFilter(field_name='database__name', lookup_expr='in')\n    name = CharInFilter(field_name='name', lookup_expr='in')\n\n    class Meta:\n        model = Schema\n        fields = ['name']\n\n\nclass TableFilter(PropertyFilterSet):\n    name = CharInFilter(field_name='name', lookup_expr='in')\n    created = DateTimeFromToRangeFilter(field_name='created_at')\n    updated = DateTimeFromToRangeFilter(field_name='updated_at')\n    not_imported = BooleanFilter(lookup_expr=\"isnull\", field_name='import_verified')\n\n    class Meta:\n        model = Table\n        fields = ['name', 'schema', 'created_at', 'updated_at', 'import_verified']\n\n\nclass DatabaseFilter(PropertyFilterSet):\n    class Meta:\n        model = Database\n        fields = ['deleted']\n", "path": "mathesar/api/filters.py"}, {"content": "\"\"\"\nDjango settings for config project.\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\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\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    \"django.contrib.staticfiles\",\n    \"rest_framework\",\n    \"django_filters\",\n    \"django_property_filter\",\n    \"mathesar\",\n]\n\nMIDDLEWARE = [\n    \"django.middleware.security.SecurityMiddleware\",\n    \"django.contrib.sessions.middleware.SessionMiddleware\",\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]\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            ],\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}\nDATABASES[decouple_config('DJANGO_DATABASE_KEY')] = decouple_config('DJANGO_DATABASE_URL', cast=db_url)\n\nfor db_key, db_dict in DATABASES.items():\n    # Engine can be '.postgresql' or '.postgresql_psycopg2'\n    if not db_dict['ENGINE'].startswith('django.db.backends.postgresql'):\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\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']\nif decouple_config('TEST', default=False, cast=bool):\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# Quick-start development settings - unsuitable for production\n# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/\n\n# SECURITY WARNING: keep the secret key used in production secret!\nSECRET_KEY = decouple_config('SECRET_KEY')\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())\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\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\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)\n\nMEDIA_ROOT = os.path.join(BASE_DIR, '.media/')\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.SessionAuthentication'\n    ]\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 = 'http://localhost:3000'\n\n\nSTATICFILES_DIRS = [MATHESAR_UI_BUILD_LOCATION]\n", "path": "config/settings.py"}], "after_files": [{"content": "from django_filters import BooleanFilter, DateTimeFromToRangeFilter, OrderingFilter\nfrom django_property_filter import PropertyFilterSet, PropertyBaseInFilter, PropertyCharFilter, PropertyOrderingFilter\n\nfrom mathesar.database.types import MathesarTypeIdentifier\nfrom mathesar.models import Schema, Table, Database\n\nFILTER_OPTIONS_BY_TYPE_IDENTIFIER = {\n    MathesarTypeIdentifier.BOOLEAN.value:\n    {\n        \"db_type\": \"BOOLEAN\",\n        \"options\": [{\n            \"op\": \"eq\",\n            \"value\": {\n                \"allowed_types\": [\"BOOLEAN\"],\n            }\n        }, {\n            \"op\": \"is_null\",\n            \"value\": \"null\",\n        }]\n    }\n}\n\n\nclass CharInFilter(PropertyBaseInFilter, PropertyCharFilter):\n    pass\n\n\nclass SchemaFilter(PropertyFilterSet):\n    database = CharInFilter(field_name='database__name', lookup_expr='in')\n    name = CharInFilter(field_name='name', lookup_expr='in')\n\n    sort_by = PropertyOrderingFilter(\n        fields=(\n            ('id', 'id'),\n            ('name', 'name'),\n        ),\n        label=\"Sort By\",\n    )\n\n    class Meta:\n        model = Schema\n        fields = ['name']\n\n\nclass TableFilter(PropertyFilterSet):\n    name = CharInFilter(field_name='name', lookup_expr='in')\n    created = DateTimeFromToRangeFilter(field_name='created_at')\n    updated = DateTimeFromToRangeFilter(field_name='updated_at')\n    not_imported = BooleanFilter(lookup_expr=\"isnull\", field_name='import_verified')\n\n    sort_by = PropertyOrderingFilter(\n        fields=(\n            ('id', 'id'),\n            ('name', 'name'),\n        ),\n        label=\"Sort By\",\n    )\n\n    class Meta:\n        model = Table\n        fields = ['name', 'schema', 'created_at', 'updated_at', 'import_verified']\n\n\nclass DatabaseFilter(PropertyFilterSet):\n    sort_by = OrderingFilter(\n        fields=(\n            ('id', 'id'),\n            ('name', 'name'),\n        ),\n        label=\"Sort By\",\n    )\n\n    class Meta:\n        model = Database\n        fields = ['deleted']\n", "path": "mathesar/api/filters.py"}, {"content": "\"\"\"\nDjango settings for config project.\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\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\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    \"django.contrib.staticfiles\",\n    \"rest_framework\",\n    \"django_filters\",\n    \"django_property_filter\",\n    \"mathesar\",\n]\n\nMIDDLEWARE = [\n    \"django.middleware.security.SecurityMiddleware\",\n    \"django.contrib.sessions.middleware.SessionMiddleware\",\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]\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            ],\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}\nDATABASES[decouple_config('DJANGO_DATABASE_KEY')] = decouple_config('DJANGO_DATABASE_URL', cast=db_url)\n\nfor db_key, db_dict in DATABASES.items():\n    # Engine can be '.postgresql' or '.postgresql_psycopg2'\n    if not db_dict['ENGINE'].startswith('django.db.backends.postgresql'):\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\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']\nif decouple_config('TEST', default=False, cast=bool):\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# Quick-start development settings - unsuitable for production\n# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/\n\n# SECURITY WARNING: keep the secret key used in production secret!\nSECRET_KEY = decouple_config('SECRET_KEY')\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())\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\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\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)\n\nMEDIA_ROOT = os.path.join(BASE_DIR, '.media/')\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.SessionAuthentication'\n    ],\n    'DEFAULT_FILTER_BACKENDS': (\n        'django_filters.rest_framework.DjangoFilterBackend',\n        'rest_framework.filters.OrderingFilter',\n    ),\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 = 'http://localhost:3000'\n\n\nSTATICFILES_DIRS = [MATHESAR_UI_BUILD_LOCATION]\n", "path": "config/settings.py"}]}