fastapi-rtk 2.10.0__tar.gz → 2.10.2__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.
- fastapi_rtk-2.10.2/PKG-INFO +329 -0
- fastapi_rtk-2.10.2/README.md +280 -0
- fastapi_rtk-2.10.2/fastapi_rtk/_version.py +1 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_columns_mixin.py +3 -2
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/filters.py +10 -7
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/api/model_rest_api/test_columns.py +81 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/sqla/conftest.py +28 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/sqla/test_filters.py +32 -0
- fastapi_rtk-2.10.0/PKG-INFO +0 -47
- fastapi_rtk-2.10.0/README.md +0 -0
- fastapi_rtk-2.10.0/fastapi_rtk/_version.py +0 -1
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/.gitignore +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/LICENSE +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/base_api.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_add_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_bulk_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_delete_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_download_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_edit_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_file_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_info_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_list_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_params.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_show_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_typed_base.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/api/model_rest_api/_upload_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/apis/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/apis/info.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/apis/license.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/auth.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/hashers/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/hashers/pbkdf2.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/hashers/scrypt.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/ldap.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/password_helpers/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/password_helpers/fab.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/strategies/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/strategies/config.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/strategies/db.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/auth/strategies/jwt.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/generic/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/generic/column.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/generic/db.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/generic/exceptions.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/generic/filters.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/generic/interface.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/generic/model.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/generic/session.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/column.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/db.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/exceptions.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/extensions/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/extensions/audit/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/extensions/audit/_decorators_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/extensions/audit/_lifecycle_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/extensions/audit/_logger.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/extensions/audit/_processing_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/extensions/audit/audit.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/extensions/audit/types.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/filters.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/geometry_converter.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/interface.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/model.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/backends/sqla/session.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/bases/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/bases/db.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/bases/file_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/bases/filter.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/bases/interface.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/bases/model.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/bases/session.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/cli.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/_security_crypto.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/db/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/db/templates/fastapi/README +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/db/templates/fastapi/alembic.ini.mako +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/db/templates/fastapi/env.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/db/templates/fastapi/script.py.mako +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/README +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/alembic.ini.mako +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/env.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/script.py.mako +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/export.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/security.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/commands/translate.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/const.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/decorators.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/types.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/cli/utils.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/config.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/const.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/db.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/decorators.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/dependencies.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/exceptions.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/fastapi_react_toolkit.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/file_managers/file_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/file_managers/image_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/file_managers/s3_file_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/file_managers/s3_image_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/filters.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/globals.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/lang/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/lang/babel/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/lang/babel/cli.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/lang/babel/config.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/lang/babel.cfg +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/lang/lazy_text.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/lang/messages.pot +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.mo +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.po +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.mo +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.po +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/middlewares.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/mixins.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/models.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/py.typed +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/registry.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/routers.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/schemas.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/apis.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/models.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/security_manager/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/security_manager/_association_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/security_manager/_builtin_role_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/security_manager/_cleanup_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/security_manager/_exception_filters.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/security_manager/_export.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/security_manager/_import.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/security_manager/_role_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/security/sqla/security_manager/_user_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/setting.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/types.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/async_task_runner.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/class_factory.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/csv_json_converter.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/deep_merge.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/extender_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/flask_appbuilder_utils.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/formatter.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/hooks.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/lazy.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/merge_schema.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/multiple_async_contexts.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/pydantic.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/run_utils.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/self_dependencies.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/smartdefaultdict.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/sqla.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/timezone.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/update_signature.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/utils/use_default_when_none.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/fastapi_rtk/version.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/pyproject.toml +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/conftest.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/docker-compose.gis.yml +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/api/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/api/test_model_rest_api.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/apis/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/apis/test_info_callable_schema.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/apis/test_info_contract.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/auth/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/auth/test_auth_flow.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/auth/test_oauth.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/conftest.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/file_managers/test_file_routes.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/security/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/security/sqla/test_security_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/integration/test_app_smoke.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/api/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/api/conftest.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/api/model_rest_api/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/api/model_rest_api/test_file_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/api/model_rest_api/test_init.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/api/model_rest_api/test_typed_base_consistency.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/api/test_base_api.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/apis/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/apis/test_info.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/apis/test_license.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/auth/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/auth/hashers/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/auth/hashers/test_pbkdf2.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/auth/hashers/test_scrypt.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/auth/password_helpers/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/auth/password_helpers/test_fab.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/auth/strategies/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/auth/strategies/test_config.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/auth/strategies/test_db.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/auth/strategies/test_jwt.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/auth/test_auth.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/generic/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/generic/test_column.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/generic/test_db.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/generic/test_exceptions.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/generic/test_filters.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/generic/test_interface.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/generic/test_model.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/generic/test_session.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/sqla/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/sqla/test_audit.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/sqla/test_audit_types.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/sqla/test_column.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/sqla/test_db.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/sqla/test_geoalchemy2.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/sqla/test_interface.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/sqla/test_model.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/backends/sqla/test_session.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/bases/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/bases/test_db.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/bases/test_file_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/bases/test_filter.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/bases/test_interface.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/bases/test_model.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/bases/test_session.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/commands/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/commands/conftest.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/commands/test_db.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/commands/test_export.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/commands/test_security.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/commands/test_security_crypto.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/commands/test_translate.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/conftest.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/test_cli.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/test_decorators.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/test_types.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/cli/test_utils.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/file_managers/conftest.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/file_managers/test_file_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/file_managers/test_image_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/file_managers/test_s3_file_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/file_managers/test_s3_image_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/lang/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/lang/test_babel_cli.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/lang/test_babel_config.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/lang/test_lazy_text.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/security/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/security/sqla/conftest.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/security/sqla/test_apis.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/security/sqla/test_models.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/security/sqla/test_security_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_config.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_const.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_db.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_decorators.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_dependencies.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_exceptions.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_fastapi_react_toolkit.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_filters.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_globals.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_manager.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_middlewares.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_mixins.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_models.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_registry.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_routers.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_schemas.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_setting.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_types.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/test_version.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/__init__.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_async_task_runner.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_class_factory.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_csv_json_converter.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_deep_merge.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_extender_mixin.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_flask_appbuilder_utils.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_formatter.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_hooks.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_lazy.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_merge_schema.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_multiple_async_contexts.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_pydantic.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_run_utils.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_self_dependencies.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_smartdefaultdict.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_sqla.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_timezone.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_update_signature.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/tests/unit/utils/test_use_default_when_none.py +0 -0
- {fastapi_rtk-2.10.0 → fastapi_rtk-2.10.2}/uv.lock +0 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastapi-rtk
|
|
3
|
+
Version: 2.10.2
|
|
4
|
+
Summary: A package that provides a set of tools to build a FastAPI application with a Class-Based CRUD API.
|
|
5
|
+
Project-URL: Homepage, https://codeberg.org/datatactics/fastapi-rtk
|
|
6
|
+
Project-URL: Issues, https://codeberg.org/datatactics/fastapi-rtk/issues
|
|
7
|
+
Author-email: Matthias Leinweber <m.leinweber@datatactics.de>, Agustinus Nicander Hery <a.hery@datatactics.de>
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Requires-Dist: alembic>=1.17.0
|
|
18
|
+
Requires-Dist: beautifulsoup4>=4.14.2
|
|
19
|
+
Requires-Dist: fastapi-babel>=1.0.0
|
|
20
|
+
Requires-Dist: fastapi-users[oauth,sqlalchemy]>=15.0.5
|
|
21
|
+
Requires-Dist: fastapi[standard]>=0.119.1
|
|
22
|
+
Requires-Dist: jsonschema2md>=1.7.0
|
|
23
|
+
Requires-Dist: marshmallow-sqlalchemy>=1.4.2
|
|
24
|
+
Requires-Dist: pip-licenses>=5.5.1
|
|
25
|
+
Requires-Dist: polib>=1.2.0
|
|
26
|
+
Requires-Dist: prometheus-fastapi-instrumentator>=7.1.0
|
|
27
|
+
Requires-Dist: secweb>=1.25.2
|
|
28
|
+
Requires-Dist: sqlalchemy-utils>=0.42.0
|
|
29
|
+
Requires-Dist: werkzeug>=3.1.5
|
|
30
|
+
Provides-Extra: audit-bg
|
|
31
|
+
Requires-Dist: apscheduler>=3.11.2; extra == 'audit-bg'
|
|
32
|
+
Provides-Extra: fab
|
|
33
|
+
Requires-Dist: prison>=0.2.1; extra == 'fab'
|
|
34
|
+
Provides-Extra: geometry
|
|
35
|
+
Requires-Dist: geoalchemy2>=0.18.1; extra == 'geometry'
|
|
36
|
+
Requires-Dist: shapely>=2.1.2; extra == 'geometry'
|
|
37
|
+
Provides-Extra: ldap
|
|
38
|
+
Requires-Dist: ldap3>=2.9.1; extra == 'ldap'
|
|
39
|
+
Provides-Extra: profiler
|
|
40
|
+
Requires-Dist: pyinstrument>=5.1.2; extra == 'profiler'
|
|
41
|
+
Provides-Extra: s3
|
|
42
|
+
Requires-Dist: smart-open[s3]>=7.5.0; extra == 's3'
|
|
43
|
+
Provides-Extra: test
|
|
44
|
+
Requires-Dist: aiosqlite>=0.21.0; extra == 'test'
|
|
45
|
+
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'test'
|
|
46
|
+
Requires-Dist: pytest-cov>=7.0.0; extra == 'test'
|
|
47
|
+
Requires-Dist: pytest>=9.0.2; extra == 'test'
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# FastAPI React Toolkit
|
|
51
|
+
|
|
52
|
+
A set of extensions for [FastAPI](https://github.com/tiangolo/fastapi) and a React component library for building modern web applications with [Mantine](https://mantine.dev/), [Zustand](https://zustand.docs.pmnd.rs/), [TanStack Query](https://tanstack.com/query/latest), and [JsonForms](https://jsonforms.io/).
|
|
53
|
+
|
|
54
|
+
## Concept
|
|
55
|
+
|
|
56
|
+
FastAPI React Toolkit bootstraps a web API with [FastAPI](https://github.com/tiangolo/fastapi) and provides a React component library for building a SPA frontend. It supports automatic CRUD API generation, RBAC, OAuth2/JWT authentication, database migrations, and i18n.
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
- Automatic CRUD API generation from SQLAlchemy models
|
|
61
|
+
- Role-Based Access Control (RBAC)
|
|
62
|
+
- Database migrations (Alembic)
|
|
63
|
+
- OAuth2/JWT authentication
|
|
64
|
+
- Modular backend and frontend
|
|
65
|
+
- React hooks and components for API, Auth, Language, DataGrid, UserMenu, etc.
|
|
66
|
+
- Built-in i18n for backend and frontend
|
|
67
|
+
|
|
68
|
+
## Getting Started
|
|
69
|
+
|
|
70
|
+
You can use `fastapi-rtk create-app` command to quickly set up a new project with the recommended structure and example code.
|
|
71
|
+
|
|
72
|
+
### Recommended Project Structure
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
project/
|
|
76
|
+
├── app/
|
|
77
|
+
│ ├── __init__.py # Configuration loading
|
|
78
|
+
│ ├── app.py # FastAPI app initialization
|
|
79
|
+
│ ├── config.py # Settings
|
|
80
|
+
│ ├── models.py # Database models
|
|
81
|
+
│ └── apis.py # API endpoints
|
|
82
|
+
├── webapp/
|
|
83
|
+
│ ├── src/
|
|
84
|
+
│ │ ├── main.jsx # React app entry point
|
|
85
|
+
│ │ ├── App.jsx # Main app component
|
|
86
|
+
│ │ ├── constants.js # Constants for the frontend, like BASE_PATH
|
|
87
|
+
│ │ └── ... # Other React components and hooks
|
|
88
|
+
│ ├── index.html # HTML template
|
|
89
|
+
└── run.py # Entry point for development server
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Backend
|
|
93
|
+
|
|
94
|
+
1. Install FastAPI React Toolkit:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pip install fastapi-rtk
|
|
98
|
+
mkdir -p app
|
|
99
|
+
touch run.py app/__init__.py app/app.py app/config.py app/models.py app/apis.py
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
2. Project files:
|
|
103
|
+
|
|
104
|
+
**app/\_\_init\_\_.py**
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from fastapi_rtk import g
|
|
108
|
+
|
|
109
|
+
g.config.from_pyfile("./app/config.py")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**app/app.py**
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from fastapi import FastAPI
|
|
116
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
117
|
+
from fastapi_rtk import FastAPIReactToolkit
|
|
118
|
+
|
|
119
|
+
app = FastAPI(docs_url="/openapi/v1")
|
|
120
|
+
|
|
121
|
+
app.add_middleware(
|
|
122
|
+
CORSMiddleware,
|
|
123
|
+
allow_origins=["http://localhost:5173"],
|
|
124
|
+
allow_credentials=True,
|
|
125
|
+
allow_methods=["*"],
|
|
126
|
+
allow_headers=["*"],
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
toolkit = FastAPIReactToolkit(
|
|
130
|
+
app,
|
|
131
|
+
create_tables=True, # Dev: auto-create tables
|
|
132
|
+
upgrade_db=False, # Prod: run migrations
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
from .apis import * # noqa: E402, F403
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**app/config.py**
|
|
139
|
+
|
|
140
|
+
See more configuration [here](https://codeberg.org/datatactics/fastapi-rtk/wiki/03-Configuration).
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
import os
|
|
144
|
+
|
|
145
|
+
basedir = os.path.abspath(os.path.dirname(__file__))
|
|
146
|
+
|
|
147
|
+
# Required settings
|
|
148
|
+
SECRET_KEY = "your-secure-secret-key"
|
|
149
|
+
SQLALCHEMY_DATABASE_URI = "sqlite+aiosqlite:///" + os.path.join(basedir, "app.db")
|
|
150
|
+
|
|
151
|
+
# Optional settings
|
|
152
|
+
APP_NAME = "My FastAPI-RTK App"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**app/models.py**
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from fastapi_rtk import Model, Mapped, mapped_column, relationship
|
|
159
|
+
from sqlalchemy import String, ForeignKey
|
|
160
|
+
|
|
161
|
+
class Category(Model):
|
|
162
|
+
__tablename__ = "categories"
|
|
163
|
+
|
|
164
|
+
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
165
|
+
name: Mapped[str] # Automatically set the column to String
|
|
166
|
+
|
|
167
|
+
items: Mapped[list["Item"]] = relationship(back_populates="category")
|
|
168
|
+
|
|
169
|
+
def __repr__(self):
|
|
170
|
+
return self.name
|
|
171
|
+
|
|
172
|
+
class Item(Model):
|
|
173
|
+
__tablename__ = "items"
|
|
174
|
+
|
|
175
|
+
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
176
|
+
name: Mapped[str] = mapped_column(String(100)) # Can also be explicitly given
|
|
177
|
+
description: Mapped[str | None]
|
|
178
|
+
|
|
179
|
+
category_id: Mapped[int | None] = mapped_column(ForeignKey("categories.id"))
|
|
180
|
+
category: Mapped[Category | None] = relationship(back_populates="items")
|
|
181
|
+
|
|
182
|
+
def __repr__(self):
|
|
183
|
+
return self.name
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**app/apis.py**
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from fastapi_rtk import ModelRestApi, SQLAInterface, g
|
|
190
|
+
from .models import Item, Category
|
|
191
|
+
|
|
192
|
+
class ItemApi(ModelRestApi):
|
|
193
|
+
resource_name = "items"
|
|
194
|
+
datamodel = SQLAInterface(Item)
|
|
195
|
+
|
|
196
|
+
class CategoryApi(ModelRestApi):
|
|
197
|
+
resource_name = "categories"
|
|
198
|
+
datamodel = SQLAInterface(Category)
|
|
199
|
+
|
|
200
|
+
g.current_app.add_api(ItemApi)
|
|
201
|
+
g.current_app.add_api(CategoryApi)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
It will create the following CRUD endpoints automatically, all under the resource prefix `/api/v1/items`:
|
|
205
|
+
|
|
206
|
+
- `GET /api/v1/items/_image/{filename}` - Serve image files (If image column is present)
|
|
207
|
+
- `GET /api/v1/items/_file/{filename}` - Serve file downloads (If file column is present)
|
|
208
|
+
- `GET /api/v1/items/_info` - Get metadata about the model, including which columns can be added, edited, filtered, etc.
|
|
209
|
+
- `POST /api/v1/items/bulk/{handler}` - Bulk operations, if set on the API class
|
|
210
|
+
- `GET /api/v1/items/download` - Download items as CSV
|
|
211
|
+
- `GET /api/v1/items/` - List items
|
|
212
|
+
- `POST /api/v1/items/` - Create item
|
|
213
|
+
- `GET /api/v1/items/{id}` - Get item by ID
|
|
214
|
+
- `PUT /api/v1/items/{id}` - Update item by ID
|
|
215
|
+
- `DELETE /api/v1/items/{id}` - Delete item by ID
|
|
216
|
+
|
|
217
|
+
### Frontend
|
|
218
|
+
|
|
219
|
+
1. Install React dependencies:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
pnpm install @mantine/core @mantine/dates @mantine/form @mantine/hooks dayjs react react-dom react-router fastapi-rtk
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
2. Project files:
|
|
226
|
+
|
|
227
|
+
**webapp/index.html**
|
|
228
|
+
|
|
229
|
+
```html
|
|
230
|
+
<!DOCTYPE html>
|
|
231
|
+
<html lang="en">
|
|
232
|
+
<head>
|
|
233
|
+
<meta charset="UTF-8" />
|
|
234
|
+
<base href="%VITE_BASE_PATH%" />
|
|
235
|
+
<link rel="icon" type="image/svg+xml" href="" />
|
|
236
|
+
<meta
|
|
237
|
+
name="viewport"
|
|
238
|
+
content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
|
239
|
+
/>
|
|
240
|
+
<title>YOUR_APP_NAME_HERE</title>
|
|
241
|
+
<script src="%VITE_BASE_PATH%server-config.js"></script>
|
|
242
|
+
<script nonce="{{nonce}}">
|
|
243
|
+
window.nonce = "{{nonce}}";
|
|
244
|
+
</script>
|
|
245
|
+
</head>
|
|
246
|
+
<body>
|
|
247
|
+
<div id="root"></div>
|
|
248
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
249
|
+
</body>
|
|
250
|
+
</html>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**src/main.jsx**
|
|
254
|
+
|
|
255
|
+
```jsx
|
|
256
|
+
import "@mantine/core/styles.css";
|
|
257
|
+
import "@mantine/dates/styles.css";
|
|
258
|
+
// Other Mantine styles can be imported here if needed
|
|
259
|
+
|
|
260
|
+
import "fastapi-rtk/styles.css";
|
|
261
|
+
import "./index.css";
|
|
262
|
+
|
|
263
|
+
import { MantineProvider } from "@mantine/core";
|
|
264
|
+
import { Provider } from "fastapi-rtk";
|
|
265
|
+
import { StrictMode } from "react";
|
|
266
|
+
import { createRoot } from "react-dom/client";
|
|
267
|
+
import { BrowserRouter } from "react-router";
|
|
268
|
+
import App from "./App.jsx";
|
|
269
|
+
import { BASE_PATH } from "./constants.js";
|
|
270
|
+
|
|
271
|
+
createRoot(document.getElementById("root")).render(
|
|
272
|
+
<StrictMode>
|
|
273
|
+
<MantineProvider>
|
|
274
|
+
<Provider baseUrl={BASE_PATH + "api/v1"}>
|
|
275
|
+
<BrowserRouter basename={BASE_PATH}>
|
|
276
|
+
<App />
|
|
277
|
+
</BrowserRouter>
|
|
278
|
+
</Provider>
|
|
279
|
+
</MantineProvider>
|
|
280
|
+
</StrictMode>,
|
|
281
|
+
);
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**src/constants.js**
|
|
285
|
+
|
|
286
|
+
```javascript
|
|
287
|
+
export const BASE_PATH = new URL(document.baseURI).pathname;
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Platform Adapters (React Native)
|
|
291
|
+
|
|
292
|
+
The frontend package is split in two: a Mantine/DOM-free package published as the `fastapi-rtk/api` subpath, and the Mantine-based web package (`fastapi-rtk` / `fastapi-rtk/core`). Every place the library touches the platform (storage, HTTP, cookies/tokens, file downloads, OAuth popups, `FormData`) goes through six small adapter interfaces (plus an optional localization adapter), grouped into an `Adapters` object. `fastapi-rtk` ships web defaults built on the DOM (cookie auth, `localStorage`, `fetch`, ...), so existing web apps need no changes.
|
|
293
|
+
|
|
294
|
+
An optional `fastapi-rtk/react-native-adapters` package provides factory functions (`createReactNativeAdapters`, plus per-adapter factories) that build the same six adapters on top of React Native / Expo primitives, using bearer JWT auth (`auth/jwt/login`) instead of the web's cookie auth (`auth/login`):
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
import { ApiProvider, Provider, useAuth } from "fastapi-rtk/api";
|
|
298
|
+
import { useApi } from "fastapi-rtk/contexts";
|
|
299
|
+
import { createReactNativeAdapters } from "fastapi-rtk/react-native-adapters";
|
|
300
|
+
|
|
301
|
+
const rnAdapters = createReactNativeAdapters({
|
|
302
|
+
asyncStorage,
|
|
303
|
+
fileSystem,
|
|
304
|
+
sharing,
|
|
305
|
+
webBrowser,
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
<Provider baseUrl="https://api.example.com/api/v1" adapters={rnAdapters}>
|
|
309
|
+
<ApiProvider resource_name="items">
|
|
310
|
+
{/* your own RN UI, driven by useApi()/useAuth() */}
|
|
311
|
+
</ApiProvider>
|
|
312
|
+
</Provider>;
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
A single adapter can also be swapped on the web `Provider` via `adapters={{ storage: mine }}` (merged per-key over the web defaults; the rest stay web defaults).
|
|
316
|
+
|
|
317
|
+
See the wiki page [React Native and Adapters](https://codeberg.org/datatactics/fastapi-rtk/wiki/06.04-React-Native-and-Adapters) for the full adapter reference (interfaces, per-adapter web/RN table, auth transports).
|
|
318
|
+
|
|
319
|
+
## License
|
|
320
|
+
|
|
321
|
+
FastAPI-RTK is licensed under the [MIT license](https://codeberg.org/datatactics/fastapi-rtk/src/branch/main/LICENSE).
|
|
322
|
+
|
|
323
|
+
## Contributing
|
|
324
|
+
|
|
325
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
For more details, see the [Wiki](https://codeberg.org/datatactics/fastapi-rtk/wiki) and the [example app](https://codeberg.org/datatactics/fastapi-rtk/src/branch/main/py/example/app/readme.md).
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# FastAPI React Toolkit
|
|
2
|
+
|
|
3
|
+
A set of extensions for [FastAPI](https://github.com/tiangolo/fastapi) and a React component library for building modern web applications with [Mantine](https://mantine.dev/), [Zustand](https://zustand.docs.pmnd.rs/), [TanStack Query](https://tanstack.com/query/latest), and [JsonForms](https://jsonforms.io/).
|
|
4
|
+
|
|
5
|
+
## Concept
|
|
6
|
+
|
|
7
|
+
FastAPI React Toolkit bootstraps a web API with [FastAPI](https://github.com/tiangolo/fastapi) and provides a React component library for building a SPA frontend. It supports automatic CRUD API generation, RBAC, OAuth2/JWT authentication, database migrations, and i18n.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Automatic CRUD API generation from SQLAlchemy models
|
|
12
|
+
- Role-Based Access Control (RBAC)
|
|
13
|
+
- Database migrations (Alembic)
|
|
14
|
+
- OAuth2/JWT authentication
|
|
15
|
+
- Modular backend and frontend
|
|
16
|
+
- React hooks and components for API, Auth, Language, DataGrid, UserMenu, etc.
|
|
17
|
+
- Built-in i18n for backend and frontend
|
|
18
|
+
|
|
19
|
+
## Getting Started
|
|
20
|
+
|
|
21
|
+
You can use `fastapi-rtk create-app` command to quickly set up a new project with the recommended structure and example code.
|
|
22
|
+
|
|
23
|
+
### Recommended Project Structure
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
project/
|
|
27
|
+
├── app/
|
|
28
|
+
│ ├── __init__.py # Configuration loading
|
|
29
|
+
│ ├── app.py # FastAPI app initialization
|
|
30
|
+
│ ├── config.py # Settings
|
|
31
|
+
│ ├── models.py # Database models
|
|
32
|
+
│ └── apis.py # API endpoints
|
|
33
|
+
├── webapp/
|
|
34
|
+
│ ├── src/
|
|
35
|
+
│ │ ├── main.jsx # React app entry point
|
|
36
|
+
│ │ ├── App.jsx # Main app component
|
|
37
|
+
│ │ ├── constants.js # Constants for the frontend, like BASE_PATH
|
|
38
|
+
│ │ └── ... # Other React components and hooks
|
|
39
|
+
│ ├── index.html # HTML template
|
|
40
|
+
└── run.py # Entry point for development server
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Backend
|
|
44
|
+
|
|
45
|
+
1. Install FastAPI React Toolkit:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install fastapi-rtk
|
|
49
|
+
mkdir -p app
|
|
50
|
+
touch run.py app/__init__.py app/app.py app/config.py app/models.py app/apis.py
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
2. Project files:
|
|
54
|
+
|
|
55
|
+
**app/\_\_init\_\_.py**
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from fastapi_rtk import g
|
|
59
|
+
|
|
60
|
+
g.config.from_pyfile("./app/config.py")
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**app/app.py**
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from fastapi import FastAPI
|
|
67
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
68
|
+
from fastapi_rtk import FastAPIReactToolkit
|
|
69
|
+
|
|
70
|
+
app = FastAPI(docs_url="/openapi/v1")
|
|
71
|
+
|
|
72
|
+
app.add_middleware(
|
|
73
|
+
CORSMiddleware,
|
|
74
|
+
allow_origins=["http://localhost:5173"],
|
|
75
|
+
allow_credentials=True,
|
|
76
|
+
allow_methods=["*"],
|
|
77
|
+
allow_headers=["*"],
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
toolkit = FastAPIReactToolkit(
|
|
81
|
+
app,
|
|
82
|
+
create_tables=True, # Dev: auto-create tables
|
|
83
|
+
upgrade_db=False, # Prod: run migrations
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
from .apis import * # noqa: E402, F403
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**app/config.py**
|
|
90
|
+
|
|
91
|
+
See more configuration [here](https://codeberg.org/datatactics/fastapi-rtk/wiki/03-Configuration).
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
import os
|
|
95
|
+
|
|
96
|
+
basedir = os.path.abspath(os.path.dirname(__file__))
|
|
97
|
+
|
|
98
|
+
# Required settings
|
|
99
|
+
SECRET_KEY = "your-secure-secret-key"
|
|
100
|
+
SQLALCHEMY_DATABASE_URI = "sqlite+aiosqlite:///" + os.path.join(basedir, "app.db")
|
|
101
|
+
|
|
102
|
+
# Optional settings
|
|
103
|
+
APP_NAME = "My FastAPI-RTK App"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**app/models.py**
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from fastapi_rtk import Model, Mapped, mapped_column, relationship
|
|
110
|
+
from sqlalchemy import String, ForeignKey
|
|
111
|
+
|
|
112
|
+
class Category(Model):
|
|
113
|
+
__tablename__ = "categories"
|
|
114
|
+
|
|
115
|
+
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
116
|
+
name: Mapped[str] # Automatically set the column to String
|
|
117
|
+
|
|
118
|
+
items: Mapped[list["Item"]] = relationship(back_populates="category")
|
|
119
|
+
|
|
120
|
+
def __repr__(self):
|
|
121
|
+
return self.name
|
|
122
|
+
|
|
123
|
+
class Item(Model):
|
|
124
|
+
__tablename__ = "items"
|
|
125
|
+
|
|
126
|
+
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
127
|
+
name: Mapped[str] = mapped_column(String(100)) # Can also be explicitly given
|
|
128
|
+
description: Mapped[str | None]
|
|
129
|
+
|
|
130
|
+
category_id: Mapped[int | None] = mapped_column(ForeignKey("categories.id"))
|
|
131
|
+
category: Mapped[Category | None] = relationship(back_populates="items")
|
|
132
|
+
|
|
133
|
+
def __repr__(self):
|
|
134
|
+
return self.name
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**app/apis.py**
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from fastapi_rtk import ModelRestApi, SQLAInterface, g
|
|
141
|
+
from .models import Item, Category
|
|
142
|
+
|
|
143
|
+
class ItemApi(ModelRestApi):
|
|
144
|
+
resource_name = "items"
|
|
145
|
+
datamodel = SQLAInterface(Item)
|
|
146
|
+
|
|
147
|
+
class CategoryApi(ModelRestApi):
|
|
148
|
+
resource_name = "categories"
|
|
149
|
+
datamodel = SQLAInterface(Category)
|
|
150
|
+
|
|
151
|
+
g.current_app.add_api(ItemApi)
|
|
152
|
+
g.current_app.add_api(CategoryApi)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
It will create the following CRUD endpoints automatically, all under the resource prefix `/api/v1/items`:
|
|
156
|
+
|
|
157
|
+
- `GET /api/v1/items/_image/{filename}` - Serve image files (If image column is present)
|
|
158
|
+
- `GET /api/v1/items/_file/{filename}` - Serve file downloads (If file column is present)
|
|
159
|
+
- `GET /api/v1/items/_info` - Get metadata about the model, including which columns can be added, edited, filtered, etc.
|
|
160
|
+
- `POST /api/v1/items/bulk/{handler}` - Bulk operations, if set on the API class
|
|
161
|
+
- `GET /api/v1/items/download` - Download items as CSV
|
|
162
|
+
- `GET /api/v1/items/` - List items
|
|
163
|
+
- `POST /api/v1/items/` - Create item
|
|
164
|
+
- `GET /api/v1/items/{id}` - Get item by ID
|
|
165
|
+
- `PUT /api/v1/items/{id}` - Update item by ID
|
|
166
|
+
- `DELETE /api/v1/items/{id}` - Delete item by ID
|
|
167
|
+
|
|
168
|
+
### Frontend
|
|
169
|
+
|
|
170
|
+
1. Install React dependencies:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
pnpm install @mantine/core @mantine/dates @mantine/form @mantine/hooks dayjs react react-dom react-router fastapi-rtk
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
2. Project files:
|
|
177
|
+
|
|
178
|
+
**webapp/index.html**
|
|
179
|
+
|
|
180
|
+
```html
|
|
181
|
+
<!DOCTYPE html>
|
|
182
|
+
<html lang="en">
|
|
183
|
+
<head>
|
|
184
|
+
<meta charset="UTF-8" />
|
|
185
|
+
<base href="%VITE_BASE_PATH%" />
|
|
186
|
+
<link rel="icon" type="image/svg+xml" href="" />
|
|
187
|
+
<meta
|
|
188
|
+
name="viewport"
|
|
189
|
+
content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
|
190
|
+
/>
|
|
191
|
+
<title>YOUR_APP_NAME_HERE</title>
|
|
192
|
+
<script src="%VITE_BASE_PATH%server-config.js"></script>
|
|
193
|
+
<script nonce="{{nonce}}">
|
|
194
|
+
window.nonce = "{{nonce}}";
|
|
195
|
+
</script>
|
|
196
|
+
</head>
|
|
197
|
+
<body>
|
|
198
|
+
<div id="root"></div>
|
|
199
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
200
|
+
</body>
|
|
201
|
+
</html>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**src/main.jsx**
|
|
205
|
+
|
|
206
|
+
```jsx
|
|
207
|
+
import "@mantine/core/styles.css";
|
|
208
|
+
import "@mantine/dates/styles.css";
|
|
209
|
+
// Other Mantine styles can be imported here if needed
|
|
210
|
+
|
|
211
|
+
import "fastapi-rtk/styles.css";
|
|
212
|
+
import "./index.css";
|
|
213
|
+
|
|
214
|
+
import { MantineProvider } from "@mantine/core";
|
|
215
|
+
import { Provider } from "fastapi-rtk";
|
|
216
|
+
import { StrictMode } from "react";
|
|
217
|
+
import { createRoot } from "react-dom/client";
|
|
218
|
+
import { BrowserRouter } from "react-router";
|
|
219
|
+
import App from "./App.jsx";
|
|
220
|
+
import { BASE_PATH } from "./constants.js";
|
|
221
|
+
|
|
222
|
+
createRoot(document.getElementById("root")).render(
|
|
223
|
+
<StrictMode>
|
|
224
|
+
<MantineProvider>
|
|
225
|
+
<Provider baseUrl={BASE_PATH + "api/v1"}>
|
|
226
|
+
<BrowserRouter basename={BASE_PATH}>
|
|
227
|
+
<App />
|
|
228
|
+
</BrowserRouter>
|
|
229
|
+
</Provider>
|
|
230
|
+
</MantineProvider>
|
|
231
|
+
</StrictMode>,
|
|
232
|
+
);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**src/constants.js**
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
export const BASE_PATH = new URL(document.baseURI).pathname;
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Platform Adapters (React Native)
|
|
242
|
+
|
|
243
|
+
The frontend package is split in two: a Mantine/DOM-free package published as the `fastapi-rtk/api` subpath, and the Mantine-based web package (`fastapi-rtk` / `fastapi-rtk/core`). Every place the library touches the platform (storage, HTTP, cookies/tokens, file downloads, OAuth popups, `FormData`) goes through six small adapter interfaces (plus an optional localization adapter), grouped into an `Adapters` object. `fastapi-rtk` ships web defaults built on the DOM (cookie auth, `localStorage`, `fetch`, ...), so existing web apps need no changes.
|
|
244
|
+
|
|
245
|
+
An optional `fastapi-rtk/react-native-adapters` package provides factory functions (`createReactNativeAdapters`, plus per-adapter factories) that build the same six adapters on top of React Native / Expo primitives, using bearer JWT auth (`auth/jwt/login`) instead of the web's cookie auth (`auth/login`):
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { ApiProvider, Provider, useAuth } from "fastapi-rtk/api";
|
|
249
|
+
import { useApi } from "fastapi-rtk/contexts";
|
|
250
|
+
import { createReactNativeAdapters } from "fastapi-rtk/react-native-adapters";
|
|
251
|
+
|
|
252
|
+
const rnAdapters = createReactNativeAdapters({
|
|
253
|
+
asyncStorage,
|
|
254
|
+
fileSystem,
|
|
255
|
+
sharing,
|
|
256
|
+
webBrowser,
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
<Provider baseUrl="https://api.example.com/api/v1" adapters={rnAdapters}>
|
|
260
|
+
<ApiProvider resource_name="items">
|
|
261
|
+
{/* your own RN UI, driven by useApi()/useAuth() */}
|
|
262
|
+
</ApiProvider>
|
|
263
|
+
</Provider>;
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
A single adapter can also be swapped on the web `Provider` via `adapters={{ storage: mine }}` (merged per-key over the web defaults; the rest stay web defaults).
|
|
267
|
+
|
|
268
|
+
See the wiki page [React Native and Adapters](https://codeberg.org/datatactics/fastapi-rtk/wiki/06.04-React-Native-and-Adapters) for the full adapter reference (interfaces, per-adapter web/RN table, auth transports).
|
|
269
|
+
|
|
270
|
+
## License
|
|
271
|
+
|
|
272
|
+
FastAPI-RTK is licensed under the [MIT license](https://codeberg.org/datatactics/fastapi-rtk/src/branch/main/LICENSE).
|
|
273
|
+
|
|
274
|
+
## Contributing
|
|
275
|
+
|
|
276
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
For more details, see the [Wiki](https://codeberg.org/datatactics/fastapi-rtk/wiki) and the [example app](https://codeberg.org/datatactics/fastapi-rtk/src/branch/main/py/example/app/readme.md).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.10.2"
|
|
@@ -632,8 +632,6 @@ class ColumnsMixin(_TypedModelRestApi):
|
|
|
632
632
|
|
|
633
633
|
value["type"] = "string"
|
|
634
634
|
params = {}
|
|
635
|
-
if not info.values:
|
|
636
|
-
params["readOnly"] = True
|
|
637
635
|
|
|
638
636
|
col_use_enum = use_enum
|
|
639
637
|
if isinstance(col_use_enum, dict):
|
|
@@ -664,6 +662,9 @@ class ColumnsMixin(_TypedModelRestApi):
|
|
|
664
662
|
value["items"] = params
|
|
665
663
|
else:
|
|
666
664
|
value.update(params)
|
|
665
|
+
|
|
666
|
+
if not info.values:
|
|
667
|
+
value["readOnly"] = True
|
|
667
668
|
else:
|
|
668
669
|
# Check for anyOf (multiple possible types) and convert it to only one type
|
|
669
670
|
anyOf = value.get("anyOf")
|
|
@@ -487,7 +487,9 @@ class FilterGlobal(BaseFilterTextContains):
|
|
|
487
487
|
filters = []
|
|
488
488
|
|
|
489
489
|
for val in value:
|
|
490
|
-
|
|
490
|
+
# Chain || instead of concat(*args): some databases cap function-call args,
|
|
491
|
+
# which wide tables exceed. coalesce keeps concat's NULL-as-empty.
|
|
492
|
+
concat_expr = None
|
|
491
493
|
rel_filter_arr = []
|
|
492
494
|
for col in cols:
|
|
493
495
|
if (
|
|
@@ -497,15 +499,16 @@ class FilterGlobal(BaseFilterTextContains):
|
|
|
497
499
|
):
|
|
498
500
|
rel_filter_arr.append(self._handle_text_contains(col, val))
|
|
499
501
|
elif col in self.datamodel.list_columns:
|
|
500
|
-
|
|
501
|
-
|
|
502
|
+
piece = sqlalchemy.func.coalesce(
|
|
503
|
+
sqlalchemy.cast(self._cast_column(col), sa_types.String), ""
|
|
504
|
+
)
|
|
505
|
+
concat_expr = (
|
|
506
|
+
piece if concat_expr is None else concat_expr + " " + piece
|
|
502
507
|
)
|
|
503
508
|
params = [*rel_filter_arr]
|
|
504
|
-
if
|
|
509
|
+
if concat_expr is not None:
|
|
505
510
|
val = val.strip().lower()
|
|
506
|
-
params.append(
|
|
507
|
-
sqlalchemy.func.concat(*concat_arr).ilike("%" + val + "%")
|
|
508
|
-
)
|
|
511
|
+
params.append(concat_expr.ilike("%" + val + "%"))
|
|
509
512
|
filters.append(sqlalchemy.or_(*params))
|
|
510
513
|
return statement.filter(sqlalchemy.and_(*filters))
|
|
511
514
|
|