fastapi-sqlalchemy-toolkit 0.6.3__tar.gz → 0.6.5__tar.gz

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.
Files changed (28) hide show
  1. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/PKG-INFO +1 -3
  2. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/README.md +0 -2
  3. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/fastapi_sqlalchemy_toolkit/model_manager.py +50 -97
  4. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/pyproject.toml +1 -1
  5. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/.flake8 +0 -0
  6. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/.github/workflows/python-publish.yml +0 -0
  7. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/.gitignore +0 -0
  8. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/.pylintrc +0 -0
  9. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/AUTHORS +0 -0
  10. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/LICENSE +0 -0
  11. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/.env +0 -0
  12. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/__init__.py +0 -0
  13. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/api/__init__.py +0 -0
  14. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/api/api.py +0 -0
  15. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/api/endpoints/__init__.py +0 -0
  16. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/api/endpoints/child.py +0 -0
  17. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/config.py +0 -0
  18. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/db.py +0 -0
  19. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/deps.py +0 -0
  20. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/main.py +0 -0
  21. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/managers.py +0 -0
  22. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/models.py +0 -0
  23. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/examples/app/schemas.py +0 -0
  24. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/fastapi_sqlalchemy_toolkit/__init__.py +0 -0
  25. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/fastapi_sqlalchemy_toolkit/filters.py +0 -0
  26. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/fastapi_sqlalchemy_toolkit/ordering.py +0 -0
  27. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/fastapi_sqlalchemy_toolkit/utils.py +0 -0
  28. {fastapi_sqlalchemy_toolkit-0.6.3 → fastapi_sqlalchemy_toolkit-0.6.5}/requirements.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastapi_sqlalchemy_toolkit
3
- Version: 0.6.3
3
+ Version: 0.6.5
4
4
  Summary: FastAPI SQLAlchemy Toolkit
5
5
  Project-URL: Homepage, https://github.com/e-kondr01/fastapi-sqlalchemy-toolkit
6
6
  Author-email: Egor Kondrashov <e.kondr01@gmail.com>
@@ -92,8 +92,6 @@ my_model_manager = ModelManager[MyModel, MyModelCreateSchema, MyModelUpdateSchem
92
92
  - `count` - получение количества объектов
93
93
  - `update` - обновление объекта; выполняет валидацию значений полей на уровне БД
94
94
  - `delete` - удаление объекта
95
- - `bulk_create` - создание объектов пачкой; выполняет валидацию значений полей на уровне БД
96
- - `bulk_update` - обновление объектов пачкой; выполняет валидацию значений полей на уровне БД
97
95
 
98
96
  ## Фильтрация
99
97
 
@@ -75,8 +75,6 @@ my_model_manager = ModelManager[MyModel, MyModelCreateSchema, MyModelUpdateSchem
75
75
  - `count` - получение количества объектов
76
76
  - `update` - обновление объекта; выполняет валидацию значений полей на уровне БД
77
77
  - `delete` - удаление объекта
78
- - `bulk_create` - создание объектов пачкой; выполняет валидацию значений полей на уровне БД
79
- - `bulk_update` - обновление объектов пачкой; выполняет валидацию значений полей на уровне БД
80
78
 
81
79
  ## Фильтрация
82
80
 
@@ -180,7 +180,7 @@ class ModelManager(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
180
180
  **simple_filters: Any,
181
181
  ) -> ModelType | Row:
182
182
  """
183
- Получение одного экземпляра модели или возвращение HTTP ответа 404.
183
+ Получение одного экземпляра модели или вызов HTTP исключения 404.
184
184
 
185
185
  :param session: сессия SQLAlchemy
186
186
 
@@ -209,10 +209,12 @@ class ModelManager(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
209
209
  select_=select_,
210
210
  **simple_filters,
211
211
  )
212
- attrs_str = ", ".join(
213
- [f"{key}={value}" for key, value in simple_filters.items()]
214
- )
215
212
  if not db_obj:
213
+ attrs_str = ", ".join(
214
+ [f"{key}={value}" for key, value in simple_filters.items()]
215
+ )
216
+ if where:
217
+ attrs_str += f", {where}"
216
218
  raise HTTPException(
217
219
  status_code=status.HTTP_404_NOT_FOUND,
218
220
  detail=f"{self.model.__tablename__} with {attrs_str} not found",
@@ -223,7 +225,6 @@ class ModelManager(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
223
225
  self,
224
226
  session: AsyncSession,
225
227
  options: List[Any] | Any | None = None,
226
- order_by: OrderingField | None = None,
227
228
  where: Any | None = None,
228
229
  **simple_filters: Any,
229
230
  ) -> bool:
@@ -234,8 +235,6 @@ class ModelManager(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
234
235
 
235
236
  :param options: параметры для метода .options() загрузчика SQLAlchemy
236
237
 
237
- :param order_by: поле для сортировки (экземпляр OrderingField)
238
-
239
238
  :param where: выражение, которое будет передано в метод .where() SQLAlchemy
240
239
 
241
240
  :param simple_filters: параметры для фильтрации по точному соответствию,
@@ -244,12 +243,54 @@ class ModelManager(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
244
243
  :returns: True если объект существует, иначе False
245
244
  """
246
245
  stmt = self.assemble_stmt(
247
- select(self.model.id), order_by, options, where, **simple_filters
246
+ select(self.model.id), None, options, where, **simple_filters
248
247
  )
249
-
250
248
  result = await session.execute(stmt)
251
249
  return result.first() is not None
252
250
 
251
+ async def exists_or_404(
252
+ self,
253
+ session: AsyncSession,
254
+ options: List[Any] | Any | None = None,
255
+ where: Any | None = None,
256
+ **simple_filters: Any,
257
+ ) -> bool:
258
+ """
259
+ Проверка существования экземпляра модели.
260
+ Если объект не существует, вызывает HTTP исключение 404.
261
+
262
+ :param session: сессия SQLAlchemy
263
+
264
+ :param options: параметры для метода .options() загрузчика SQLAlchemy
265
+
266
+ :param where: выражение, которое будет передано в метод .where() SQLAlchemy
267
+
268
+ :param simple_filters: параметры для фильтрации по точному соответствию,
269
+ аналогично методу .filter_by() SQLAlchemy
270
+
271
+ :returns: True, если объект существует
272
+
273
+ :raises: fastapi.HTTPException 404
274
+ """
275
+
276
+ exists = await self.exists(
277
+ session,
278
+ options=options,
279
+ where=where,
280
+ **simple_filters,
281
+ )
282
+ if not exists:
283
+ attrs_str = ", ".join(
284
+ [f"{key}={value}" for key, value in simple_filters.items()]
285
+ )
286
+ if where:
287
+ attrs_str += f", {where}"
288
+ raise HTTPException(
289
+ status_code=status.HTTP_404_NOT_FOUND,
290
+ detail=f"{self.model.__tablename__} with {attrs_str} does not exist",
291
+ )
292
+ return True
293
+
253
294
  async def paginated_filter(
254
295
  self,
255
296
  session: AsyncSession,
@@ -579,94 +620,6 @@ class ModelManager(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
579
620
  await session.commit()
580
621
  return db_obj
581
622
 
582
- async def bulk_create(
583
- self,
584
- session: AsyncSession,
585
- in_objs: List[CreateSchemaType | dict],
586
- commit: bool = True,
587
- **attrs: Any,
588
- ) -> List[ModelType]:
589
- """
590
- Создание экземпляров модели и сохранение в БД пачкой.
591
- Также выполняет валидацию на уровне БД.
592
-
593
- :param session: сессия SQLAlchemy
594
-
595
- :param in_objs: список значений полей создаваемых экземпляров модели
596
-
597
- :param commit: нужно ли вызывать `session.commit()`
598
-
599
- :param attrs: дополнительные значения полей создаваемого экземпляра
600
- (чтобы какие-то поля можно было установить напрямую из кода,
601
- например, пользователя запроса)
602
-
603
- :returns: список созданных экземпляров модели
604
- """
605
- objs = []
606
- for in_obj in in_objs:
607
- if not isinstance(in_obj, dict):
608
- in_obj = in_obj.model_dump()
609
- in_obj.update(**attrs)
610
- await self.run_db_validation(session, in_obj=in_obj)
611
- db_obj = self.model(**in_obj)
612
- objs.append(db_obj)
613
- session.add_all(objs)
614
- if commit:
615
- await session.commit()
616
- for db_obj in objs:
617
- await session.refresh(db_obj)
618
- return objs
619
-
620
- async def bulk_update(
621
- self,
622
- session: AsyncSession,
623
- in_objs: dict[ModelType, UpdateSchemaType],
624
- commit: bool = True,
625
- exclude_unset: bool = True,
626
- **attrs: Any,
627
- ) -> List[ModelType]:
628
- """
629
- Обновление экземпляров модели в БД пачкой.
630
- Также выполняет валидацию на уровне БД.
631
-
632
- :param session: сессия SQLAlchemy
633
-
634
- :param db_obj: обновляемый объект
635
-
636
- :param in_objs: словарь обновляемых объектов, где ключ -- существующий объект,
637
- значение -- схема Pydantic для обновления значений его полей.
638
-
639
- :param commit: нужно ли вызывать `session.commit()`
640
-
641
- :param exclude_unset: передаётся в метод `.model_dump()` Pydantic модели.
642
- При использовании метода в PATCH-запросах имеет смысл оставлять его True
643
- для изменения только переданных полей; при PUT-запросах имеет смысл
644
- передавать False, чтобы установить дефолтные значения полей, заданные
645
- в модели Pydantic.
646
-
647
- :param attrs: дополнительные значения обновляемых полей
648
- (чтобы какие-то поля можно было установить напрямую из кода,
649
- например, пользователя запроса)
650
-
651
- :returns: список обновлённых экземпляров модели
652
- """
653
- for obj, in_obj in in_objs.items():
654
- if isinstance(in_obj, dict):
655
- update_data = in_obj
656
- else:
657
- update_data = in_obj.model_dump(exclude_unset=exclude_unset)
658
- update_data.update(attrs)
659
- await self.run_db_validation(session, db_obj=obj, in_obj=update_data)
660
- for field in update_data:
661
- setattr(obj, field, update_data[field])
662
- session.add(obj)
663
- if commit:
664
- await session.commit()
665
- updated_objs = list(in_objs.keys())
666
- for updated_obj in updated_objs:
667
- await session.refresh(updated_obj)
668
- return updated_objs
669
-
670
623
  ##################################################################################
671
624
  # Internal methods
672
625
  ##################################################################################
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "fastapi_sqlalchemy_toolkit"
7
- version = "0.6.3"
7
+ version = "0.6.5"
8
8
  authors = [
9
9
  { name="Egor Kondrashov", email="e.kondr01@gmail.com" },
10
10
  ]