brilliance-admin 0.44.1__py3-none-any.whl → 0.44.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -122,6 +122,7 @@ class SQLAlchemyJWTAdminAuthentication(AdminAuthentication):
122
122
  try:
123
123
  async with self.db_async_session() as session:
124
124
  result = await session.execute(stmt)
125
+ user = result.scalar_one_or_none()
125
126
 
126
127
  except ConnectionRefusedError as e:
127
128
  logger.exception(
@@ -133,8 +134,6 @@ class SQLAlchemyJWTAdminAuthentication(AdminAuthentication):
133
134
  status_code=500,
134
135
  ) from e
135
136
 
136
- user = result.scalar_one_or_none()
137
-
138
137
  if not user:
139
138
  raise AdminAPIException(
140
139
  APIError(message="User not found", code="user_not_found"),
@@ -6,7 +6,7 @@ from brilliance_admin.auth import UserABC
6
6
  from brilliance_admin.exceptions import AdminAPIException, APIError, FieldError
7
7
  from brilliance_admin.schema.category import FieldSchemaData
8
8
  from brilliance_admin.schema.table.fields.base import TableField
9
- from brilliance_admin.schema.table.table_models import Record
9
+ from brilliance_admin.schema.table.table_models import AutocompleteData, Record
10
10
  from brilliance_admin.translations import LanguageContext
11
11
  from brilliance_admin.translations import TranslateText as _
12
12
  from brilliance_admin.utils import DeserializeAction
@@ -96,10 +96,9 @@ class SQLAlchemyRelatedField(TableField):
96
96
  msg = f'Cannot resolve target model for FK "{field_slug}"'
97
97
  raise AttributeError(msg)
98
98
 
99
- async def autocomplete(self, model, data, user, *, extra: dict | None = None) -> List[Record]:
99
+ async def autocomplete(self, model, data: AutocompleteData, user, *, extra: dict | None = None) -> List[Record]:
100
100
  # pylint: disable=import-outside-toplevel
101
101
  from sqlalchemy import select
102
- from sqlalchemy.sql import expression
103
102
 
104
103
  if extra is None or extra.get('db_async_session') is None:
105
104
  msg = f'SQLAlchemyRelatedField.autocomplete {type(self).__name__} requires extra["db_async_session"] (AsyncSession)'
@@ -113,23 +112,37 @@ class SQLAlchemyRelatedField(TableField):
113
112
  limit = min(150, data.limit)
114
113
  stmt = select(target_model).limit(limit)
115
114
 
115
+ pk = get_pk(target_model)
116
+ python_pk_type = pk.property.columns[0].type.python_type
117
+
116
118
  if data.search_string:
117
- if hasattr(target_model, 'id'):
118
- stmt = stmt.where(getattr(target_model, 'id') == data.search_string)
119
+ try:
120
+ value = python_pk_type(data.search_string)
121
+ except (ValueError, TypeError):
122
+ # Search string cannot be cast to primary key type, skip id filter
123
+ value = None
124
+
125
+ stmt = stmt.where(pk == value)
119
126
 
120
127
  # Add already selected choices
121
- existed_choices = []
122
128
  if data.existed_choices:
123
129
  existed_choices = [i['key'] for i in data.existed_choices if 'key' in i]
124
130
 
125
- if existed_choices and hasattr(target_model, 'id'):
126
- stmt = stmt.where(getattr(target_model, 'id').in_(existed_choices) | expression.true())
131
+ values = []
132
+ for value in existed_choices:
133
+ try:
134
+ values.append(python_pk_type(value))
135
+ except (ValueError, TypeError) as e:
136
+ msg = f'Invalid existed_choices value "{value}" for pk {pk} python_pk_type:{python_pk_type.__name__}'
137
+ raise AdminAPIException(APIError(message=msg), status_code=500) from e
138
+
139
+ stmt = stmt.where(pk.in_(values))
127
140
 
128
141
  async with db_async_session() as session:
129
142
  records = (await session.execute(stmt)).scalars().all()
130
143
 
131
144
  for record in records:
132
- results.append(Record(key=getattr(record, 'id'), title=str(record)))
145
+ results.append(Record(key=getattr(record, pk.key), title=str(record)))
133
146
 
134
147
  return results
135
148
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brilliance-admin
3
- Version: 0.44.1
3
+ Version: 0.44.2
4
4
  Summary: Simple and lightweight data managment framework powered by FastAPI and Vue3 Vuetify all-in-one. Some call it heavenly in its brilliance.
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.10
@@ -18,6 +18,7 @@ Requires-Dist: structlog>=25.5.0; extra == "example"
18
18
  Requires-Dist: rich>=14.2.0; extra == "example"
19
19
  Requires-Dist: asyncpg>=0.31.0; extra == "example"
20
20
  Requires-Dist: pydantic-settings>=2.12.0; extra == "example"
21
+ Requires-Dist: twine; extra == "example"
21
22
  Provides-Extra: tests
22
23
  Requires-Dist: pytest>=8.4.2; extra == "tests"
23
24
  Requires-Dist: pytest-asyncio>=1.2.0; extra == "tests"
@@ -17,9 +17,9 @@ brilliance_admin/api/views/settings.py,sha256=2A9suZQONEtW9LkFban29Fe5ipQaaGT0Cz
17
17
  brilliance_admin/api/views/table.py,sha256=ZCckiEaBVAF7Px-oDWkFkL4F3KmFJi-70LSqFXomovk,5939
18
18
  brilliance_admin/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  brilliance_admin/integrations/sqlalchemy/__init__.py,sha256=AmQHOvegS6_uaE4xYDHzRMdA9PyHn0cCt1s1IWc9G2U,318
20
- brilliance_admin/integrations/sqlalchemy/auth.py,sha256=NvOLKeeSJuNTzFhisNO9R3sEmGRS8IQrCwghPrtuzaw,4924
20
+ brilliance_admin/integrations/sqlalchemy/auth.py,sha256=N9CjFfnXmKeNbJBxHMDlbPaTQPmYWlYTz_73PYBkaNk,4931
21
21
  brilliance_admin/integrations/sqlalchemy/autocomplete.py,sha256=Q2BDwPL3d7FErqYkO-s6Q6pDg2PTZ1RUUAWc9tbllT8,1436
22
- brilliance_admin/integrations/sqlalchemy/fields.py,sha256=piLGzX24GwCuWEBo7Jy0_8pMeiWc8tl9nj6Qt6ehYaY,9390
22
+ brilliance_admin/integrations/sqlalchemy/fields.py,sha256=7D0E4-12rqraqHek2yNuHzRdO7hhxjp0edhJu-mTnWQ,9897
23
23
  brilliance_admin/integrations/sqlalchemy/fields_schema.py,sha256=7WkOrt5dVvrsZppNZEZS8QaQPMSrfcWChwOaOFSRVOg,11419
24
24
  brilliance_admin/integrations/sqlalchemy/table/__init__.py,sha256=g_in2pLTi8UQnT5uNFA8mLW5mxlT84irQ7yVaP_OSS4,605
25
25
  brilliance_admin/integrations/sqlalchemy/table/base.py,sha256=-osqhTvqE7YcBxsAjqIUMWyYk1df04GIDmdvtieTXcg,4885
@@ -28,8 +28,6 @@ brilliance_admin/integrations/sqlalchemy/table/delete.py,sha256=toH9at-MAWO46K_4
28
28
  brilliance_admin/integrations/sqlalchemy/table/list.py,sha256=WPH4GoLrIU-TcGMrNoq46i3sJIz6vV76UaacmtG3Ytk,6720
29
29
  brilliance_admin/integrations/sqlalchemy/table/retrieve.py,sha256=O6mJ_XxfLJ59Hx_V5VdAZNxObkY6p5L7gZED8QGXfy0,2744
30
30
  brilliance_admin/integrations/sqlalchemy/table/update.py,sha256=RfIXTQHHEoZCrOtVeOxZ3ql0-is5czsgVAfO_1_gF7w,3578
31
- brilliance_admin/locales/en.yml,sha256=o57Bhh5Z8zC2A1Y2h-iw4t6h9vjhAFQS0mw9J8t2nio,1287
32
- brilliance_admin/locales/ru.yml,sha256=qquuAGkViLrNtgO0REWXZXlz1Ri2avFS1VmtAeTYwK0,1878
33
31
  brilliance_admin/schema/__init__.py,sha256=tZIRTSKFsNOmDqjoAgtYthYrT8ljPvLnYRzfupBLT00,290
34
32
  brilliance_admin/schema/admin_schema.py,sha256=9w88GuogRjdphFuDdx7On553qHTwGoJVCyKpooFSKQ8,6723
35
33
  brilliance_admin/schema/category.py,sha256=D2aIpDyL-2CibkpenNu8uyh4AzOdQ2ArTDltVYS7xZQ,6592
@@ -66,8 +64,8 @@ brilliance_admin/static/tinymce/plugins/codesample/css/prism.css,sha256=exAdMtHb
66
64
  brilliance_admin/static/tinymce/plugins/customLink/plugin.js,sha256=illBNpnHDkBsLG6wo_jDPF6z7CGnO1MQWUoDwZKy6vQ,5589
67
65
  brilliance_admin/static/tinymce/plugins/customLink/css/link.css,sha256=gh5nvY8Z92hJfCEBPnIm4jIPCcKKbJnab-30oIfX7Hc,56
68
66
  brilliance_admin/templates/index.html,sha256=JK7a-EQtaRweQJ1KoXc3L82M4d7GSCXJEe85cxuvWaQ,1294
69
- brilliance_admin-0.44.1.dist-info/licenses/LICENSE,sha256=rgWE5Cxk53W0PhTOVmcQedABEWN1QMG-PRz3fz531sE,1074
70
- brilliance_admin-0.44.1.dist-info/METADATA,sha256=KB9guzLv6WvBDCLv4c93VsKUZ3x6byNXBu3wjw00ZVg,6910
71
- brilliance_admin-0.44.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
- brilliance_admin-0.44.1.dist-info/top_level.txt,sha256=almFFSWrVYieI3i54hYL0fMUaeuIYiazS2Kx4wtK-ns,17
73
- brilliance_admin-0.44.1.dist-info/RECORD,,
67
+ brilliance_admin-0.44.2.dist-info/licenses/LICENSE,sha256=rgWE5Cxk53W0PhTOVmcQedABEWN1QMG-PRz3fz531sE,1074
68
+ brilliance_admin-0.44.2.dist-info/METADATA,sha256=2XEOEkHyDGd1r6fz3neNPvp6oQAfS8ZocAERObr20pY,6951
69
+ brilliance_admin-0.44.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
70
+ brilliance_admin-0.44.2.dist-info/top_level.txt,sha256=almFFSWrVYieI3i54hYL0fMUaeuIYiazS2Kx4wtK-ns,17
71
+ brilliance_admin-0.44.2.dist-info/RECORD,,
@@ -1,27 +0,0 @@
1
- delete: 'Delete'
2
- delete_confirmation_text: "Are you sure you want to delete those records?\nThis action cannot be undone."
3
- deleted_successfully: 'The entries were successfully deleted.'
4
-
5
- errors:
6
- pk_not_found: 'The "%(pk_name)s" field was not found in the submitted data.'
7
- record_not_found: 'No record found for %(pk_name)s=%(pk)s.'
8
- db_error_create: 'Error creating a record in the database.'
9
- db_error_update: 'Error updating the record in the database.'
10
- db_error_retrieve: 'Error retrieving the record from the database.'
11
- db_error_list: 'Failed to retrieve table data from the database.'
12
- connection_refused_error: 'Database connection error: %(error)s'
13
- filters_exception: 'An unknown technical error occurred while filtering data.'
14
- method_not_allowed: 'Error, method not allowed. This action is not permitted.'
15
- filter_error: 'An error occurred during filtering: {error}'
16
- serialize_field_error: 'Serialize error: %(error)s'
17
- bad_type_error: 'Invalid data type: %(type)s but %(expected)s expected'
18
-
19
- search_help: 'Available search fields: %(fields)s'
20
- sqlalchemy_search_help: |
21
- <b>Available search fields:</b>
22
- %(fields)s
23
-
24
- <b>Available operators:</b>
25
- <b>""</b> - quotes for exact match
26
- <b>%%</b> - any sequence of characters
27
- <b>_</b> - any single character
@@ -1,27 +0,0 @@
1
- delete: 'Удалить'
2
- delete_confirmation_text: "Вы уверены, что хотите удалить данные записи?\nДанное действие нельзя отменить."
3
- deleted_successfully: 'Записи успешно удалены.'
4
-
5
- errors:
6
- pk_not_found: 'Поле "%(pk_name)s" не найдено среди переданных данных.'
7
- record_not_found: 'Запись по ключу %(pk_name)s=%(pk)s не найдена.'
8
- db_error_create: 'Ошибка создания записи в базе данных.'
9
- db_error_update: 'Ошибка обновления записи в базе данных.'
10
- db_error_retrieve: 'Ошибка получения записи из базы данных.'
11
- db_error_list: 'Ошибка получения данных таблицы из базы данных.'
12
- connection_refused_error: 'Ошибка подключения к базе данных: %(error)s'
13
- filters_exception: 'Произошла неизвестная техническая ошибка при фильтрации данных.'
14
- method_not_allowed: 'Ошибка, данный метод недоступен.'
15
- filter_error: 'Проишла ошибка при фильтрации: %(error)s'
16
- serialize_field_error: 'Ошибка чтения данных: %(error)s'
17
- bad_type_error: 'Некорректный тип данных: %(type)s; ожидается %(expected)s'
18
-
19
- search_help: 'Доступные поля для поиска: %(fields)s'
20
- sqlalchemy_search_help: |
21
- <b>Доступные поля для поиска:</b>
22
- %(fields)s
23
-
24
- <b>Доступные операторы:</b>
25
- <b>""</b> - кавычки для точного совпадения
26
- <b>%%</b> - любая последовательность символов
27
- <b>_</b> - один любой символ