fastapi-admin-kit 0.2.0__tar.gz → 0.3.0__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_admin_kit-0.3.0/CHANGELOG.md +51 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/LICENSE +1 -1
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/PKG-INFO +106 -24
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/README.md +98 -20
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/__init__.py +8 -1
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/admin/admin_database.py +38 -13
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/admin/admin_template.py +54 -17
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/admin/builtin_models.py +78 -111
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/admin/core.py +37 -13
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/admin/state.py +4 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/api/auth.py +4 -2
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/audit/diff.py +14 -24
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/audit/listener.py +56 -29
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/__init__.py +16 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/backend.py +0 -21
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/csrf.py +44 -8
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/dependencies.py +28 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/hasher.py +10 -9
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/identity.py +8 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/auth/mixins.py +148 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/models.py +11 -8
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/auth/password.py +80 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/permissions.py +19 -4
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/auth/protocol.py +72 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/ratelimit.py +17 -1
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/session.py +29 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/auth/types.py +24 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/views.py +18 -6
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/backends/__init__.py +63 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/backends/protocols.py +196 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/backends/sqlalchemy.py +678 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/cli/__init__.py +1 -1
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/cli/helpers.py +71 -2
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/cli/migrate.py +41 -22
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/cli/permissions.py +325 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/cli/user.py +44 -33
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/config/auth.py +1 -1
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/db.py +51 -23
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/filters/__init__.py +12 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/filters/base.py +335 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/filters/registry.py +163 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/flash.py +2 -2
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/form/pipeline.py +440 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/form/types.py +129 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/inline.py +111 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/inspection/__init__.py +37 -58
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/inspection/registry.py +144 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/inspection/types.py +37 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/inspection.py +1 -1
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/modeladmin.py +33 -5
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/pagination/base.py +14 -1
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/pagination/cursor.py +25 -11
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/pagination/dynamic.py +15 -6
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/pagination/offset.py +15 -5
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/router.py +3 -3
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/schemas/__init__.py +37 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/schemas/builtin.py +164 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/schemas/schema.py +119 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/search_utils.py +108 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/static/css/admin.css +22 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/static/js/admin.js +128 -44
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/form.html +13 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/users/form.html +16 -66
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/templates/partials/inline_stacked.html +179 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/templates/partials/inline_tabular.html +180 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/templates/partials/permission_widget.html +65 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/topbar.html +5 -5
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/types.py +46 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/ui/__init__.py +1 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/ui/types.py +35 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/views/__init__.py +80 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/audit.py +16 -23
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/class_views.py +423 -85
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/context.py +7 -241
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/views/factory.py +14 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/views/file_handler.py +96 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/views/form.py +89 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/views/list_context.py +459 -0
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/views/model_saver.py +395 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/profile.py +1 -1
- fastapi_admin_kit-0.3.0/fastapi_admin_kit/views/renderers.py +423 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/roles.py +13 -21
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/sidebar.py +18 -10
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/users.py +9 -17
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views.py +1 -1
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/widgets/resolver.py +1 -1
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/mkdocs.yml +9 -1
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/pyproject.toml +14 -9
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/admin.py +0 -716
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/auth/mixins.py +0 -87
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/auth/password.py +0 -37
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/auth/protocol.py +0 -22
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/cli/permissions.py +0 -184
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/filters/base.py +0 -170
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/filters/registry.py +0 -62
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/form/pipeline.py +0 -118
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/inspection/registry.py +0 -249
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/search_utils.py +0 -71
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/templates/partials/permission_widget.html +0 -113
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/types.py +0 -148
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/views/__init__.py +0 -78
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/views/factory.py +0 -630
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/views/form.py +0 -161
- fastapi_admin_kit-0.2.0/fastapi_admin_kit/views/renderers.py +0 -607
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/.gitignore +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/actions/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/actions/base.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/actions/registry.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/admin/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/admin/admin_config.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/admin/admin_router.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/admin/decorators.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/api/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/api/crud.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/api/deps.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/api/roles.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/api/schema_generator.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/api/schemas.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/api/search.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/audit/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/audit/context.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/audit/event_bus.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/audit/events.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/audit/logger.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/audit/middleware.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/audit/models.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/audit/sqlalchemy_logger.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/router.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/auth/totp.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/cli/__main__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/cli/scaffold.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/config/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/config/audit.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/config/behavior.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/config/database.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/config/nav.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/config/storage.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/config/theme.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/config/ui.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/dashboard/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/exceptions.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/field_types.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/form/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/models/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/models/base.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/nav.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/pagination/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/plugins/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/py.typed +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/registry/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/registry/core.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/registry/validation.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/registry.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/static/css/presets.css +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/static/css/tokens.css +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/static/css/variables.css +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/static/icons/heroicons.svg +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/static/js/htmx-config.js +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/storage/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/storage/base.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/storage/local.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/base.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/macros/form_fields.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/macros/icons.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/macros/table.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/macros/widgets.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/2fa/setup.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/2fa/verify.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/403.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/audit_detail.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/audit_log.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/dashboard.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/detail.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/list.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/login.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/profile/password.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/profile/profile.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/role_form.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/roles/form.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/roles/list.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/roles.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/search.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/settings/theme.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/pages/users/list.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/_inline_edit_row.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/command_palette.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/field_wrapper.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/flash_messages.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/head.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/head_minimal.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/inline_edit_form.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/list_table.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/mobile_backdrop.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/pagination.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/perm_select_widget.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/scripts.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/templates/partials/sidebar.html +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/validation.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/bulk.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/dashboard.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/delete.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/extra.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/list.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/protocols.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/search.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/settings.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/views/totp.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/widgets/__init__.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/widgets/base.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/widgets/inputs.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/widgets/registry.py +0 -0
- {fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/widgets/relation.py +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.1] - 2026-07-20
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Zero-config auto-discovery of SQLAlchemy models
|
|
12
|
+
- Built-in authentication with session-based cookies
|
|
13
|
+
- Role-based access control (RBAC) with per-model permissions
|
|
14
|
+
- Direct per-user permission overrides
|
|
15
|
+
- Audit logging with full change diffs
|
|
16
|
+
- Modern UI with Tailwind CSS, HTMX, and Alpine.js
|
|
17
|
+
- Global search / command palette (`Cmd+K` / `Ctrl+K`)
|
|
18
|
+
- Inline editing from list view with 3-dot action menu
|
|
19
|
+
- CLI tools (`fak-admin` / `fak`) for user management
|
|
20
|
+
- Async-first architecture with PostgreSQL, MySQL, and SQLite support
|
|
21
|
+
- SQLModel support via optional extra
|
|
22
|
+
- Custom widgets, themes, and templates
|
|
23
|
+
- Search and filtering with relation field lookups
|
|
24
|
+
- Bulk operations
|
|
25
|
+
- Dark mode with theme presets
|
|
26
|
+
- Pagination strategies (offset, cursor, dynamic)
|
|
27
|
+
- File uploads with local storage backend
|
|
28
|
+
- Plugin system for extensibility
|
|
29
|
+
- CSRF protection on all state-changing requests
|
|
30
|
+
- Rate limiting on authentication endpoints
|
|
31
|
+
- Environment badge for staging/production identification
|
|
32
|
+
|
|
33
|
+
### Security
|
|
34
|
+
- SQL injection prevention via identifier validation in CLI migrate and auto-migrate
|
|
35
|
+
- Secure session cookies with `SameSite=Strict` and `Secure` by default
|
|
36
|
+
- CSRF protection on all state-changing requests
|
|
37
|
+
- Rate limiting on authentication endpoints
|
|
38
|
+
- bcrypt password hashing
|
|
39
|
+
- Secret key validated to be >= 32 characters at startup
|
|
40
|
+
- Removed weak default credentials from examples
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
- `uvicorn` and `pyjwt` moved to optional `[full]` extra (no longer hard dependencies)
|
|
44
|
+
- All library code uses `logging` instead of `print()` statements
|
|
45
|
+
- Silent exception blocks now log at debug level instead of silently swallowing
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
- `__all__` in `views/__init__.py` no longer references undefined symbols
|
|
49
|
+
- Debug print statement removed from `cli/helpers.py`
|
|
50
|
+
- Line length violations in `admin/builtin_models.py`
|
|
51
|
+
- Import sorting in `admin/admin_database.py` and `cli/migrate.py`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-admin-kit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Drop-in admin panel for FastAPI + SQLAlchemy + SQLModel apps
|
|
5
5
|
Project-URL: Homepage, https://github.com/borhanst/fastapi-admin-kit
|
|
6
6
|
Project-URL: Documentation, https://borhanst.github.io/fastapi-admin-kit/
|
|
@@ -10,7 +10,7 @@ Author-email: Borhan <mdborhan.st@gmail.com>
|
|
|
10
10
|
License: MIT
|
|
11
11
|
License-File: LICENSE
|
|
12
12
|
Keywords: admin,admin-panel,async,crud,dashboard,fastapi,rbac,sqlalchemy,sqlmodel
|
|
13
|
-
Classifier: Development Status ::
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
14
|
Classifier: Framework :: AsyncIO
|
|
15
15
|
Classifier: Framework :: FastAPI
|
|
16
16
|
Classifier: Intended Audience :: Developers
|
|
@@ -28,21 +28,25 @@ Requires-Dist: bcrypt>=4.0.0
|
|
|
28
28
|
Requires-Dist: fastapi>=0.100.0
|
|
29
29
|
Requires-Dist: itsdangerous>=2.2.0
|
|
30
30
|
Requires-Dist: jinja2>=3.1.0
|
|
31
|
-
Requires-Dist:
|
|
31
|
+
Requires-Dist: pre-commit>=4.6.0
|
|
32
32
|
Requires-Dist: python-multipart>=0.0.9
|
|
33
33
|
Requires-Dist: sqlalchemy>=2.0.0
|
|
34
|
-
Requires-Dist: uvicorn>=0.30.0
|
|
35
34
|
Provides-Extra: dev
|
|
36
35
|
Requires-Dist: hatch>=1.13.0; extra == 'dev'
|
|
37
36
|
Requires-Dist: httpx>=0.27.0; extra == 'dev'
|
|
38
37
|
Requires-Dist: pre-commit>=3.5.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: pyjwt>=2.13.0; extra == 'dev'
|
|
39
39
|
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
40
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
|
|
40
41
|
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
41
42
|
Requires-Dist: ruff>=0.5.0; extra == 'dev'
|
|
42
43
|
Provides-Extra: docs
|
|
43
44
|
Requires-Dist: mkdocs-material>=9.5.0; extra == 'docs'
|
|
44
45
|
Requires-Dist: mkdocs>=1.6.0; extra == 'docs'
|
|
45
46
|
Requires-Dist: mkdocstrings[python]>=0.25.0; extra == 'docs'
|
|
47
|
+
Provides-Extra: full
|
|
48
|
+
Requires-Dist: pyjwt>=2.13.0; extra == 'full'
|
|
49
|
+
Requires-Dist: uvicorn>=0.30.0; extra == 'full'
|
|
46
50
|
Provides-Extra: mysql
|
|
47
51
|
Requires-Dist: aiomysql>=0.2.0; extra == 'mysql'
|
|
48
52
|
Provides-Extra: postgres
|
|
@@ -56,40 +60,74 @@ Description-Content-Type: text/markdown
|
|
|
56
60
|
[](https://pypi.org/project/fastapi-admin-kit/)
|
|
57
61
|
[](https://pypi.org/project/fastapi-admin-kit/)
|
|
58
62
|
[](https://github.com/borhanst/fastapi-admin-kit/blob/main/LICENSE)
|
|
63
|
+
[](https://github.com/borhanst/fastapi-admin-kit/actions/workflows/tests.yml)
|
|
59
64
|
|
|
60
|
-
A drop-in admin panel for FastAPI + SQLAlchemy apps, inspired by Django Unfold.
|
|
65
|
+
A drop-in admin panel for FastAPI + SQLAlchemy + SQLModel apps, inspired by Django Unfold.
|
|
61
66
|
|
|
62
|
-
|
|
67
|
+

|
|
63
68
|
|
|
64
69
|
📖 **[Documentation](https://borhanst.github.io/fastapi-admin-kit/)** | 🚀 **[Quick Start](#quick-start)** | 📦 **[PyPI](https://pypi.org/project/fastapi-admin-kit/)**
|
|
65
70
|
|
|
66
71
|
## Features
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
73
|
+
> See the **[Full Features List](https://borhanst.github.io/fastapi-admin-kit/guide/features/)** for every feature with detailed docs links.
|
|
74
|
+
|
|
75
|
+
- **Zero-Config Auto-Discovery** — Register a model, get full CRUD UI automatically
|
|
76
|
+
- **SQLAlchemy & SQLModel** — Works with both ORMs out of the box
|
|
77
|
+
- **Built-in Auth & RBAC** — Session-based auth with role-based permissions per model
|
|
78
|
+
- **Audit Logging** — Every create, update, and delete is recorded with full diffs
|
|
79
|
+
- **Modern UI** — Tailwind CSS, HTMX, and Alpine.js with dark mode
|
|
80
|
+
- **17 Built-in Widgets** — TextInput, Toggle, DatePicker, FileUpload, Wysiwyg, and more
|
|
81
|
+
- **Inline Editing** — Edit records directly from list view with 3-dot action menu
|
|
82
|
+
- **Command Palette** — `Cmd+K` / `Ctrl+K` global search across models and fields
|
|
83
|
+
- **JSON API** — REST endpoints with JWT token auth for external frontends
|
|
84
|
+
- **Dashboard** — Configurable stat cards, charts, tables, and progress bars
|
|
85
|
+
- **CLI Tools** — `fak-admin` / `fak` for superuser management and project scaffolding
|
|
86
|
+
- **Pagination** — Offset, cursor, or dynamic strategies per model
|
|
87
|
+
- **Filters** — Text, boolean, relation, and enum sidebar filters
|
|
88
|
+
- **File Uploads** — Built-in local storage backend with upload widgets
|
|
89
|
+
- **Async-First** — PostgreSQL, MySQL, and SQLite with auto URL normalization
|
|
90
|
+
- **CSRF & Rate Limiting** — Security built-in out of the box
|
|
75
91
|
|
|
76
92
|
## Installation
|
|
77
93
|
|
|
78
94
|
```bash
|
|
95
|
+
# pip
|
|
79
96
|
pip install fastapi-admin-kit
|
|
97
|
+
|
|
98
|
+
# uv
|
|
99
|
+
uv add fastapi-admin-kit
|
|
80
100
|
```
|
|
81
101
|
|
|
82
102
|
For database-specific async drivers:
|
|
83
103
|
|
|
84
104
|
```bash
|
|
105
|
+
# pip
|
|
85
106
|
pip install fastapi-admin-kit[postgres] # PostgreSQL via asyncpg
|
|
86
107
|
pip install fastapi-admin-kit[mysql] # MySQL via aiomysql
|
|
108
|
+
|
|
109
|
+
# uv
|
|
110
|
+
uv add fastapi-admin-kit[postgres] # PostgreSQL via asyncpg
|
|
111
|
+
uv add fastapi-admin-kit[mysql] # MySQL via aiomysql
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
For the full experience with uvicorn and JWT support:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# pip
|
|
118
|
+
pip install fastapi-admin-kit[full]
|
|
119
|
+
|
|
120
|
+
# uv
|
|
121
|
+
uv add fastapi-admin-kit[full]
|
|
87
122
|
```
|
|
88
123
|
|
|
89
124
|
## Quick Start
|
|
90
125
|
|
|
91
126
|
```python
|
|
127
|
+
import os
|
|
128
|
+
import secrets
|
|
92
129
|
from contextlib import asynccontextmanager
|
|
130
|
+
|
|
93
131
|
from fastapi import FastAPI
|
|
94
132
|
from sqlalchemy import Column, Float, Integer, String
|
|
95
133
|
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
|
|
@@ -123,8 +161,8 @@ class Product(Base):
|
|
|
123
161
|
price = Column(Float, nullable=False)
|
|
124
162
|
|
|
125
163
|
|
|
126
|
-
DATABASE_URL = "sqlite+aiosqlite:///./app.db"
|
|
127
|
-
SECRET_KEY = "
|
|
164
|
+
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite+aiosqlite:///./app.db")
|
|
165
|
+
SECRET_KEY = os.getenv("SECRET_KEY", secrets.token_urlsafe(32))
|
|
128
166
|
|
|
129
167
|
engine = create_async_engine(DATABASE_URL)
|
|
130
168
|
async_session = sessionmaker(engine, class_=AsyncSession)
|
|
@@ -151,6 +189,21 @@ admin = Admin(
|
|
|
151
189
|
admin.register(Product)
|
|
152
190
|
```
|
|
153
191
|
|
|
192
|
+
Run with:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
pip install fastapi-admin-kit[full]
|
|
196
|
+
uvicorn main:app --reload
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Open [http://localhost:8000/admin/](http://localhost:8000/admin/) and log in with:
|
|
200
|
+
|
|
201
|
+
- **Email:** `admin@example.com`
|
|
202
|
+
- **Password:** `admin`
|
|
203
|
+
|
|
204
|
+
!!! warning
|
|
205
|
+
Change the default password immediately in production!
|
|
206
|
+
|
|
154
207
|
## CLI Usage
|
|
155
208
|
|
|
156
209
|
Both the full name and the short alias work interchangeably:
|
|
@@ -167,6 +220,13 @@ fak users
|
|
|
167
220
|
# Change a user's password
|
|
168
221
|
fak-admin changepassword -e admin@example.com -p newpassword
|
|
169
222
|
fak changepassword -e admin@example.com -p newpassword
|
|
223
|
+
|
|
224
|
+
# Scaffold a new fastapi project
|
|
225
|
+
fak init myproject
|
|
226
|
+
|
|
227
|
+
# Permission management
|
|
228
|
+
fak createpermissions --base myapp.models.Base
|
|
229
|
+
fak createpermissions myapp.models.User myapp.models.Product
|
|
170
230
|
```
|
|
171
231
|
|
|
172
232
|
All commands accept `-d DATABASE_URL` or read the `DATABASE_URL` environment variable.
|
|
@@ -178,11 +238,14 @@ All commands accept `-d DATABASE_URL` or read the `DATABASE_URL` environment var
|
|
|
178
238
|
| Variable | Description | Default |
|
|
179
239
|
|---|---|---|
|
|
180
240
|
| `DATABASE_URL` | Async database connection string | `sqlite+aiosqlite:///./app.db` |
|
|
181
|
-
| `SECRET_KEY` | Signing key for sessions/CSRF/JWT (min 32 chars) |
|
|
241
|
+
| `SECRET_KEY` | Signing key for sessions/CSRF/JWT (min 32 chars) | Auto-generated if unset |
|
|
182
242
|
|
|
183
243
|
### Admin Options
|
|
184
244
|
|
|
185
245
|
```python
|
|
246
|
+
from fastapi_admin_kit import Admin
|
|
247
|
+
from fastapi_admin_kit.config import ThemeConfig
|
|
248
|
+
|
|
186
249
|
admin = Admin(
|
|
187
250
|
app=app,
|
|
188
251
|
engine=engine,
|
|
@@ -191,8 +254,6 @@ admin = Admin(
|
|
|
191
254
|
title="My Admin", # Admin panel title
|
|
192
255
|
admin_path="/admin", # URL prefix
|
|
193
256
|
dark_mode_default=False, # Dark mode on by default
|
|
194
|
-
# Theme
|
|
195
|
-
theme=ThemeConfig(preset="modern", primary_color="#6366F1"),
|
|
196
257
|
# Auth
|
|
197
258
|
auth_backend=BuiltinAuthBackend(),
|
|
198
259
|
# Environment badge
|
|
@@ -207,21 +268,42 @@ admin = Admin(
|
|
|
207
268
|
- **PostgreSQL**: `pip install fastapi-admin-kit[postgres]` + set `DATABASE_URL=postgresql+asyncpg://...`
|
|
208
269
|
- **MySQL**: `pip install fastapi-admin-kit[mysql]` + set `DATABASE_URL=mysql+aiomysql://...`
|
|
209
270
|
|
|
271
|
+
### Optional Dependencies
|
|
272
|
+
|
|
273
|
+
| Extra | Packages | When to use |
|
|
274
|
+
|---|---|---|
|
|
275
|
+
| `full` | `uvicorn`, `pyjwt` | Running the dev server or using JWT API auth |
|
|
276
|
+
| `postgres` | `asyncpg` | PostgreSQL databases |
|
|
277
|
+
| `mysql` | `aiomysql` | MySQL databases |
|
|
278
|
+
| `sqlmodel` | `sqlmodel` | Using SQLModel models |
|
|
279
|
+
| `docs` | `mkdocs`, `mkdocs-material` | Building documentation |
|
|
280
|
+
|
|
281
|
+
## Security
|
|
282
|
+
|
|
283
|
+
- Session cookies use `SameSite=Strict` and `Secure` by default
|
|
284
|
+
- CSRF protection on all state-changing requests
|
|
285
|
+
- Rate limiting on authentication endpoints
|
|
286
|
+
- Passwords hashed with bcrypt
|
|
287
|
+
- SQL injection prevention via identifier validation
|
|
288
|
+
- Secret key validated to be >= 32 characters at startup
|
|
289
|
+
|
|
210
290
|
## Development
|
|
211
291
|
|
|
212
292
|
```bash
|
|
213
293
|
# Install with dev dependencies
|
|
214
|
-
|
|
294
|
+
uv sync
|
|
215
295
|
|
|
216
|
-
# Run tests
|
|
217
|
-
pytest
|
|
296
|
+
# Run tests with coverage
|
|
297
|
+
uv run pytest --cov=fastapi_admin_kit
|
|
218
298
|
|
|
219
299
|
# Lint
|
|
220
|
-
ruff check fastapi_admin_kit/
|
|
300
|
+
uv run ruff check fastapi_admin_kit/
|
|
301
|
+
|
|
302
|
+
# Format
|
|
303
|
+
uv run ruff format fastapi_admin_kit/
|
|
221
304
|
|
|
222
305
|
# Build distribution
|
|
223
|
-
|
|
224
|
-
hatch build
|
|
306
|
+
uv build
|
|
225
307
|
```
|
|
226
308
|
|
|
227
309
|
## License
|
|
@@ -3,40 +3,74 @@
|
|
|
3
3
|
[](https://pypi.org/project/fastapi-admin-kit/)
|
|
4
4
|
[](https://pypi.org/project/fastapi-admin-kit/)
|
|
5
5
|
[](https://github.com/borhanst/fastapi-admin-kit/blob/main/LICENSE)
|
|
6
|
+
[](https://github.com/borhanst/fastapi-admin-kit/actions/workflows/tests.yml)
|
|
6
7
|
|
|
7
|
-
A drop-in admin panel for FastAPI + SQLAlchemy apps, inspired by Django Unfold.
|
|
8
|
+
A drop-in admin panel for FastAPI + SQLAlchemy + SQLModel apps, inspired by Django Unfold.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+

|
|
10
11
|
|
|
11
12
|
📖 **[Documentation](https://borhanst.github.io/fastapi-admin-kit/)** | 🚀 **[Quick Start](#quick-start)** | 📦 **[PyPI](https://pypi.org/project/fastapi-admin-kit/)**
|
|
12
13
|
|
|
13
14
|
## Features
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
16
|
+
> See the **[Full Features List](https://borhanst.github.io/fastapi-admin-kit/guide/features/)** for every feature with detailed docs links.
|
|
17
|
+
|
|
18
|
+
- **Zero-Config Auto-Discovery** — Register a model, get full CRUD UI automatically
|
|
19
|
+
- **SQLAlchemy & SQLModel** — Works with both ORMs out of the box
|
|
20
|
+
- **Built-in Auth & RBAC** — Session-based auth with role-based permissions per model
|
|
21
|
+
- **Audit Logging** — Every create, update, and delete is recorded with full diffs
|
|
22
|
+
- **Modern UI** — Tailwind CSS, HTMX, and Alpine.js with dark mode
|
|
23
|
+
- **17 Built-in Widgets** — TextInput, Toggle, DatePicker, FileUpload, Wysiwyg, and more
|
|
24
|
+
- **Inline Editing** — Edit records directly from list view with 3-dot action menu
|
|
25
|
+
- **Command Palette** — `Cmd+K` / `Ctrl+K` global search across models and fields
|
|
26
|
+
- **JSON API** — REST endpoints with JWT token auth for external frontends
|
|
27
|
+
- **Dashboard** — Configurable stat cards, charts, tables, and progress bars
|
|
28
|
+
- **CLI Tools** — `fak-admin` / `fak` for superuser management and project scaffolding
|
|
29
|
+
- **Pagination** — Offset, cursor, or dynamic strategies per model
|
|
30
|
+
- **Filters** — Text, boolean, relation, and enum sidebar filters
|
|
31
|
+
- **File Uploads** — Built-in local storage backend with upload widgets
|
|
32
|
+
- **Async-First** — PostgreSQL, MySQL, and SQLite with auto URL normalization
|
|
33
|
+
- **CSRF & Rate Limiting** — Security built-in out of the box
|
|
22
34
|
|
|
23
35
|
## Installation
|
|
24
36
|
|
|
25
37
|
```bash
|
|
38
|
+
# pip
|
|
26
39
|
pip install fastapi-admin-kit
|
|
40
|
+
|
|
41
|
+
# uv
|
|
42
|
+
uv add fastapi-admin-kit
|
|
27
43
|
```
|
|
28
44
|
|
|
29
45
|
For database-specific async drivers:
|
|
30
46
|
|
|
31
47
|
```bash
|
|
48
|
+
# pip
|
|
32
49
|
pip install fastapi-admin-kit[postgres] # PostgreSQL via asyncpg
|
|
33
50
|
pip install fastapi-admin-kit[mysql] # MySQL via aiomysql
|
|
51
|
+
|
|
52
|
+
# uv
|
|
53
|
+
uv add fastapi-admin-kit[postgres] # PostgreSQL via asyncpg
|
|
54
|
+
uv add fastapi-admin-kit[mysql] # MySQL via aiomysql
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
For the full experience with uvicorn and JWT support:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# pip
|
|
61
|
+
pip install fastapi-admin-kit[full]
|
|
62
|
+
|
|
63
|
+
# uv
|
|
64
|
+
uv add fastapi-admin-kit[full]
|
|
34
65
|
```
|
|
35
66
|
|
|
36
67
|
## Quick Start
|
|
37
68
|
|
|
38
69
|
```python
|
|
70
|
+
import os
|
|
71
|
+
import secrets
|
|
39
72
|
from contextlib import asynccontextmanager
|
|
73
|
+
|
|
40
74
|
from fastapi import FastAPI
|
|
41
75
|
from sqlalchemy import Column, Float, Integer, String
|
|
42
76
|
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
|
|
@@ -70,8 +104,8 @@ class Product(Base):
|
|
|
70
104
|
price = Column(Float, nullable=False)
|
|
71
105
|
|
|
72
106
|
|
|
73
|
-
DATABASE_URL = "sqlite+aiosqlite:///./app.db"
|
|
74
|
-
SECRET_KEY = "
|
|
107
|
+
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite+aiosqlite:///./app.db")
|
|
108
|
+
SECRET_KEY = os.getenv("SECRET_KEY", secrets.token_urlsafe(32))
|
|
75
109
|
|
|
76
110
|
engine = create_async_engine(DATABASE_URL)
|
|
77
111
|
async_session = sessionmaker(engine, class_=AsyncSession)
|
|
@@ -98,6 +132,21 @@ admin = Admin(
|
|
|
98
132
|
admin.register(Product)
|
|
99
133
|
```
|
|
100
134
|
|
|
135
|
+
Run with:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
pip install fastapi-admin-kit[full]
|
|
139
|
+
uvicorn main:app --reload
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Open [http://localhost:8000/admin/](http://localhost:8000/admin/) and log in with:
|
|
143
|
+
|
|
144
|
+
- **Email:** `admin@example.com`
|
|
145
|
+
- **Password:** `admin`
|
|
146
|
+
|
|
147
|
+
!!! warning
|
|
148
|
+
Change the default password immediately in production!
|
|
149
|
+
|
|
101
150
|
## CLI Usage
|
|
102
151
|
|
|
103
152
|
Both the full name and the short alias work interchangeably:
|
|
@@ -114,6 +163,13 @@ fak users
|
|
|
114
163
|
# Change a user's password
|
|
115
164
|
fak-admin changepassword -e admin@example.com -p newpassword
|
|
116
165
|
fak changepassword -e admin@example.com -p newpassword
|
|
166
|
+
|
|
167
|
+
# Scaffold a new fastapi project
|
|
168
|
+
fak init myproject
|
|
169
|
+
|
|
170
|
+
# Permission management
|
|
171
|
+
fak createpermissions --base myapp.models.Base
|
|
172
|
+
fak createpermissions myapp.models.User myapp.models.Product
|
|
117
173
|
```
|
|
118
174
|
|
|
119
175
|
All commands accept `-d DATABASE_URL` or read the `DATABASE_URL` environment variable.
|
|
@@ -125,11 +181,14 @@ All commands accept `-d DATABASE_URL` or read the `DATABASE_URL` environment var
|
|
|
125
181
|
| Variable | Description | Default |
|
|
126
182
|
|---|---|---|
|
|
127
183
|
| `DATABASE_URL` | Async database connection string | `sqlite+aiosqlite:///./app.db` |
|
|
128
|
-
| `SECRET_KEY` | Signing key for sessions/CSRF/JWT (min 32 chars) |
|
|
184
|
+
| `SECRET_KEY` | Signing key for sessions/CSRF/JWT (min 32 chars) | Auto-generated if unset |
|
|
129
185
|
|
|
130
186
|
### Admin Options
|
|
131
187
|
|
|
132
188
|
```python
|
|
189
|
+
from fastapi_admin_kit import Admin
|
|
190
|
+
from fastapi_admin_kit.config import ThemeConfig
|
|
191
|
+
|
|
133
192
|
admin = Admin(
|
|
134
193
|
app=app,
|
|
135
194
|
engine=engine,
|
|
@@ -138,8 +197,6 @@ admin = Admin(
|
|
|
138
197
|
title="My Admin", # Admin panel title
|
|
139
198
|
admin_path="/admin", # URL prefix
|
|
140
199
|
dark_mode_default=False, # Dark mode on by default
|
|
141
|
-
# Theme
|
|
142
|
-
theme=ThemeConfig(preset="modern", primary_color="#6366F1"),
|
|
143
200
|
# Auth
|
|
144
201
|
auth_backend=BuiltinAuthBackend(),
|
|
145
202
|
# Environment badge
|
|
@@ -154,21 +211,42 @@ admin = Admin(
|
|
|
154
211
|
- **PostgreSQL**: `pip install fastapi-admin-kit[postgres]` + set `DATABASE_URL=postgresql+asyncpg://...`
|
|
155
212
|
- **MySQL**: `pip install fastapi-admin-kit[mysql]` + set `DATABASE_URL=mysql+aiomysql://...`
|
|
156
213
|
|
|
214
|
+
### Optional Dependencies
|
|
215
|
+
|
|
216
|
+
| Extra | Packages | When to use |
|
|
217
|
+
|---|---|---|
|
|
218
|
+
| `full` | `uvicorn`, `pyjwt` | Running the dev server or using JWT API auth |
|
|
219
|
+
| `postgres` | `asyncpg` | PostgreSQL databases |
|
|
220
|
+
| `mysql` | `aiomysql` | MySQL databases |
|
|
221
|
+
| `sqlmodel` | `sqlmodel` | Using SQLModel models |
|
|
222
|
+
| `docs` | `mkdocs`, `mkdocs-material` | Building documentation |
|
|
223
|
+
|
|
224
|
+
## Security
|
|
225
|
+
|
|
226
|
+
- Session cookies use `SameSite=Strict` and `Secure` by default
|
|
227
|
+
- CSRF protection on all state-changing requests
|
|
228
|
+
- Rate limiting on authentication endpoints
|
|
229
|
+
- Passwords hashed with bcrypt
|
|
230
|
+
- SQL injection prevention via identifier validation
|
|
231
|
+
- Secret key validated to be >= 32 characters at startup
|
|
232
|
+
|
|
157
233
|
## Development
|
|
158
234
|
|
|
159
235
|
```bash
|
|
160
236
|
# Install with dev dependencies
|
|
161
|
-
|
|
237
|
+
uv sync
|
|
162
238
|
|
|
163
|
-
# Run tests
|
|
164
|
-
pytest
|
|
239
|
+
# Run tests with coverage
|
|
240
|
+
uv run pytest --cov=fastapi_admin_kit
|
|
165
241
|
|
|
166
242
|
# Lint
|
|
167
|
-
ruff check fastapi_admin_kit/
|
|
243
|
+
uv run ruff check fastapi_admin_kit/
|
|
244
|
+
|
|
245
|
+
# Format
|
|
246
|
+
uv run ruff format fastapi_admin_kit/
|
|
168
247
|
|
|
169
248
|
# Build distribution
|
|
170
|
-
|
|
171
|
-
hatch build
|
|
249
|
+
uv build
|
|
172
250
|
```
|
|
173
251
|
|
|
174
252
|
## License
|
|
@@ -5,6 +5,7 @@ from fastapi_admin_kit.admin.decorators import column
|
|
|
5
5
|
from fastapi_admin_kit.auth.mixins import AuthModelMixin
|
|
6
6
|
from fastapi_admin_kit.config import DatabaseConfig, DatabaseType
|
|
7
7
|
from fastapi_admin_kit.exceptions import ConfigError
|
|
8
|
+
from fastapi_admin_kit.inline import InlineModelAdmin, StackedInline, TabularInline
|
|
8
9
|
from fastapi_admin_kit.nav import (
|
|
9
10
|
BuiltNavGroup,
|
|
10
11
|
BuiltNavItem,
|
|
@@ -22,6 +23,7 @@ from fastapi_admin_kit.types import (
|
|
|
22
23
|
FieldsetContext,
|
|
23
24
|
FieldsetSpec,
|
|
24
25
|
FormContext,
|
|
26
|
+
InlineFormsetData,
|
|
25
27
|
PermissionSet,
|
|
26
28
|
RelationMeta,
|
|
27
29
|
SeedRole,
|
|
@@ -64,6 +66,11 @@ __all__ = [
|
|
|
64
66
|
"FieldsetContext",
|
|
65
67
|
"FieldsetSpec",
|
|
66
68
|
"FormContext",
|
|
69
|
+
"InlineFormsetData",
|
|
70
|
+
# Inline admin
|
|
71
|
+
"InlineModelAdmin",
|
|
72
|
+
"StackedInline",
|
|
73
|
+
"TabularInline",
|
|
67
74
|
# View classes
|
|
68
75
|
"BaseView",
|
|
69
76
|
"ListView",
|
|
@@ -75,4 +82,4 @@ __all__ = [
|
|
|
75
82
|
# Per-model assets
|
|
76
83
|
"AdminExtra",
|
|
77
84
|
]
|
|
78
|
-
__version__ = "0.
|
|
85
|
+
__version__ = "0.3.0"
|
{fastapi_admin_kit-0.2.0 → fastapi_admin_kit-0.3.0}/fastapi_admin_kit/admin/admin_database.py
RENAMED
|
@@ -2,13 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import logging
|
|
6
|
+
import re
|
|
5
7
|
from typing import Any
|
|
6
8
|
|
|
9
|
+
from fastapi_admin_kit.backends.sqlalchemy import SqlAlchemyDatabaseBackend
|
|
7
10
|
from fastapi_admin_kit.config.database import DatabaseConfig
|
|
8
11
|
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
_TABLE_NAME_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _validate_identifier(name: str, kind: str = "table") -> str:
|
|
18
|
+
"""Validate a SQL identifier to prevent injection."""
|
|
19
|
+
if not _TABLE_NAME_RE.match(name):
|
|
20
|
+
raise ValueError(f"Invalid {kind} name: {name!r}")
|
|
21
|
+
return name
|
|
22
|
+
|
|
9
23
|
|
|
10
24
|
class AdminDatabase:
|
|
11
|
-
"""Handles database setup, table creation, and role seeding.
|
|
25
|
+
"""Handles database setup, table creation, and role seeding.
|
|
26
|
+
|
|
27
|
+
Delegates engine creation, table creation, and auto-migration to
|
|
28
|
+
:class:`SqlAlchemyDatabaseBackend`.
|
|
29
|
+
"""
|
|
12
30
|
|
|
13
31
|
def __init__(
|
|
14
32
|
self,
|
|
@@ -19,11 +37,12 @@ class AdminDatabase:
|
|
|
19
37
|
self.engine = engine
|
|
20
38
|
self.base = base
|
|
21
39
|
self.database_config = database_config
|
|
40
|
+
self._backend = SqlAlchemyDatabaseBackend(
|
|
41
|
+
admin_database=self, database_config=database_config
|
|
42
|
+
)
|
|
22
43
|
|
|
23
44
|
def _ensure_engine(self) -> Any:
|
|
24
|
-
"""
|
|
25
|
-
Create the async engine from ``database_config`` if no engine is set.
|
|
26
|
-
"""
|
|
45
|
+
"""Create the async engine from ``database_config`` if no engine is set."""
|
|
27
46
|
if self.engine is None and self.database_config is not None:
|
|
28
47
|
self.engine = self.database_config.create_engine()
|
|
29
48
|
return self.engine
|
|
@@ -71,9 +90,11 @@ class AdminDatabase:
|
|
|
71
90
|
for table_name, table in metadata.tables.items():
|
|
72
91
|
if not inspector.has_table(table_name):
|
|
73
92
|
continue
|
|
93
|
+
safe_table = _validate_identifier(table_name)
|
|
74
94
|
existing_cols = {c["name"] for c in inspector.get_columns(table_name)}
|
|
75
95
|
for col in table.columns:
|
|
76
96
|
if col.name not in existing_cols:
|
|
97
|
+
safe_col = _validate_identifier(col.name, "column")
|
|
77
98
|
col_type = col.type.compile(self.engine.dialect)
|
|
78
99
|
nullable = "NULL" if col.nullable else "NOT NULL"
|
|
79
100
|
default = ""
|
|
@@ -85,17 +106,15 @@ class AdminDatabase:
|
|
|
85
106
|
elif col.default is not None and col.default.is_seq:
|
|
86
107
|
pass
|
|
87
108
|
sql = text(
|
|
88
|
-
f"""ALTER TABLE {
|
|
89
|
-
ADD COLUMN {
|
|
109
|
+
f"""ALTER TABLE {safe_table}
|
|
110
|
+
ADD COLUMN {safe_col} {col_type}
|
|
90
111
|
{nullable}{default}"""
|
|
91
112
|
)
|
|
92
113
|
with self.engine.begin() as conn:
|
|
93
114
|
conn.execute(sql)
|
|
94
115
|
|
|
95
116
|
def _auto_migrate(self, sync_conn: Any, metadata: Any) -> None:
|
|
96
|
-
"""
|
|
97
|
-
Add missing columns to existing tables (sync, called via run_sync).
|
|
98
|
-
"""
|
|
117
|
+
"""Add missing columns to existing tables (sync, called via run_sync)."""
|
|
99
118
|
from sqlalchemy import inspect as sa_inspect
|
|
100
119
|
from sqlalchemy import text
|
|
101
120
|
|
|
@@ -107,9 +126,11 @@ class AdminDatabase:
|
|
|
107
126
|
for table_name, table in metadata.tables.items():
|
|
108
127
|
if not inspector.has_table(table_name):
|
|
109
128
|
continue
|
|
129
|
+
safe_table = _validate_identifier(table_name)
|
|
110
130
|
existing_cols = {c["name"] for c in inspector.get_columns(table_name)}
|
|
111
131
|
for col in table.columns:
|
|
112
132
|
if col.name not in existing_cols:
|
|
133
|
+
safe_col = _validate_identifier(col.name, "column")
|
|
113
134
|
col_type = col.type.compile(dialect)
|
|
114
135
|
nullable = "NULL" if col.nullable else "NOT NULL"
|
|
115
136
|
default = ""
|
|
@@ -121,16 +142,20 @@ class AdminDatabase:
|
|
|
121
142
|
elif not col.nullable:
|
|
122
143
|
# SQLite requires a default for NOT NULL columns being added
|
|
123
144
|
type_defaults = {
|
|
124
|
-
"VARCHAR": "''",
|
|
125
|
-
"
|
|
145
|
+
"VARCHAR": "''",
|
|
146
|
+
"TEXT": "''",
|
|
147
|
+
"INTEGER": "0",
|
|
148
|
+
"FLOAT": "0.0",
|
|
149
|
+
"BOOLEAN": "0",
|
|
150
|
+
"DATETIME": "''",
|
|
126
151
|
}
|
|
127
152
|
sql_type = col_type.upper().split("(")[0]
|
|
128
153
|
temp_val = type_defaults.get(sql_type, "''")
|
|
129
154
|
default = f" DEFAULT {temp_val}"
|
|
130
155
|
sql = text(
|
|
131
|
-
f"""ALTER TABLE {
|
|
156
|
+
f"""ALTER TABLE {safe_table}
|
|
132
157
|
ADD COLUMN
|
|
133
|
-
{
|
|
158
|
+
{safe_col} {col_type} {nullable}{default}
|
|
134
159
|
"""
|
|
135
160
|
)
|
|
136
161
|
sync_conn.execute(sql)
|