|
8 | 8 | from datetime import datetime, timedelta, timezone |
9 | 9 | from enum import Enum |
10 | 10 | import os |
11 | | -from flask import current_app, abort |
| 11 | +from flask import current_app |
12 | 12 | from flask_sqlalchemy import Model |
13 | | -from marshmallow import Schema |
| 13 | +from marshmallow import Schema, fields |
14 | 14 | from pathvalidate import sanitize_filename |
15 | 15 | from sqlalchemy import Column, JSON |
16 | 16 | from sqlalchemy.sql.elements import UnaryExpression |
17 | | -from typing import Optional |
18 | | - |
| 17 | +from typing import Optional, Type |
19 | 18 |
|
20 | 19 | OrderParam = namedtuple("OrderParam", "name direction") |
21 | 20 |
|
@@ -151,14 +150,23 @@ def save_diagnostic_log_file(app: str, username: str, body: bytes) -> str: |
151 | 150 | return file_name |
152 | 151 |
|
153 | 152 |
|
154 | | -def get_schema_fields_map(schema: Schema) -> dict: |
| 153 | +def get_schema_fields_map(schema: Type[Schema]) -> dict: |
155 | 154 | """ |
156 | 155 | Creates a mapping of schema field names to corresponding DB columns. |
157 | 156 | This allows sorting by the API field name (e.g. 'size') while |
158 | 157 | actually sorting by the database column (e.g. 'disk_usage'). |
159 | 158 | """ |
160 | 159 | mapping = {} |
161 | 160 | for name, field in schema._declared_fields.items(): |
162 | | - if field and field.attribute: |
| 161 | + # some fields could have been overridden with None to be excluded |
| 162 | + if not field: |
| 163 | + continue |
| 164 | + # skip virtual fields as DB cannot sort by them |
| 165 | + if isinstance(field, (fields.Function, fields.Method)): |
| 166 | + continue |
| 167 | + if field.attribute: |
163 | 168 | mapping[name] = field.attribute |
| 169 | + # keep the map complete |
| 170 | + else: |
| 171 | + mapping[name] = name |
164 | 172 | return mapping |
0 commit comments