fastapi-admin-kit 0.1.2__tar.gz → 0.2.1__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.2.1/CHANGELOG.md +51 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/LICENSE +1 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/PKG-INFO +124 -26
- fastapi_admin_kit-0.2.1/README.md +254 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/__init__.py +3 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/actions/base.py +2 -6
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/actions/registry.py +1 -3
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/admin/admin_database.py +270 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/admin/admin_router.py +2 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/admin/admin_template.py +25 -33
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/admin/builtin_models.py +271 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/admin/core.py +70 -75
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/api/auth.py +33 -44
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/api/crud.py +9 -8
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/api/deps.py +2 -6
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/api/roles.py +7 -11
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/audit/context.py +1 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/audit/diff.py +6 -6
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/audit/event_bus.py +1 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/audit/listener.py +41 -12
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/audit/models.py +1 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/__init__.py +15 -8
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/backend.py +38 -21
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/csrf.py +71 -14
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/dependencies.py +3 -7
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/auth/hasher.py +43 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/identity.py +17 -11
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/auth/mixins.py +151 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/models.py +65 -71
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/password.py +3 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/permissions.py +16 -11
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/protocol.py +1 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/ratelimit.py +17 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/router.py +1 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/session.py +30 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/totp.py +10 -7
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/auth/views.py +82 -25
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/cli/__init__.py +19 -15
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/cli/helpers.py +172 -0
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/cli/migrate.py +266 -0
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/cli/permissions.py +324 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/cli/scaffold.py +10 -10
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/cli/user.py +207 -0
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/config/auth.py +99 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/config/behavior.py +2 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/config/nav.py +1 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/dashboard/__init__.py +6 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/filters/registry.py +3 -9
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/flash.py +4 -2
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/form/pipeline.py +2 -7
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/inspection/__init__.py +1 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/inspection/registry.py +2 -6
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/inspection.py +1 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/modeladmin.py +8 -21
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/nav.py +6 -12
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/registry/core.py +18 -14
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/registry/validation.py +2 -6
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/router.py +98 -53
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/search_utils.py +71 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/static/css/admin.css +17 -18
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/static/js/admin.js +76 -34
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/macros/form_fields.html +1 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/macros/widgets.html +33 -33
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/templates/pages/403.html +37 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/dashboard.html +31 -4
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/form.html +1 -4
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/login.html +14 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/role_form.html +2 -2
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/templates/pages/search.html +120 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/users/form.html +52 -82
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/_inline_edit_row.html +1 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/field_wrapper.html +1 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/head.html +1 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/head_minimal.html +1 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/list_table.html +1 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/mobile_backdrop.html +1 -1
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/templates/partials/perm_select_widget.html +46 -0
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/templates/partials/permission_widget.html +65 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/scripts.html +1 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/topbar.html +5 -5
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/types.py +15 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/validation.py +2 -6
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/__init__.py +0 -14
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/audit.py +43 -36
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/bulk.py +1 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/class_views.py +183 -151
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/context.py +25 -80
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/dashboard.py +63 -26
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/delete.py +1 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/factory.py +29 -70
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/form.py +11 -9
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/profile.py +11 -16
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/protocols.py +1 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/renderers.py +37 -65
- fastapi_admin_kit-0.2.1/fastapi_admin_kit/views/roles.py +310 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/search.py +1 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/settings.py +1 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/sidebar.py +33 -25
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/totp.py +7 -16
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/users.py +24 -32
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views.py +15 -15
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/widgets/inputs.py +2 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/widgets/registry.py +1 -3
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/widgets/relation.py +11 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/mkdocs.yml +9 -1
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/pyproject.toml +17 -10
- fastapi_admin_kit-0.1.2/README.md +0 -161
- fastapi_admin_kit-0.1.2/fastapi_admin_kit/admin/admin_database.py +0 -147
- fastapi_admin_kit-0.1.2/fastapi_admin_kit/admin/builtin_models.py +0 -284
- fastapi_admin_kit-0.1.2/fastapi_admin_kit/admin.py +0 -728
- fastapi_admin_kit-0.1.2/fastapi_admin_kit/cli/user.py +0 -216
- fastapi_admin_kit-0.1.2/fastapi_admin_kit/config/auth.py +0 -54
- fastapi_admin_kit-0.1.2/fastapi_admin_kit/templates/partials/permission_widget.html +0 -86
- fastapi_admin_kit-0.1.2/fastapi_admin_kit/views/roles.py +0 -259
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/.gitignore +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/actions/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/admin/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/admin/admin_config.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/admin/decorators.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/admin/state.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/api/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/api/schema_generator.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/api/schemas.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/api/search.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/audit/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/audit/events.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/audit/logger.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/audit/middleware.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/audit/sqlalchemy_logger.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/cli/__main__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/config/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/config/audit.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/config/database.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/config/storage.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/config/theme.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/config/ui.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/db.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/exceptions.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/field_types.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/filters/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/filters/base.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/form/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/models/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/models/base.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/pagination/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/pagination/base.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/pagination/cursor.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/pagination/dynamic.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/pagination/offset.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/plugins/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/py.typed +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/registry/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/registry.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/static/css/presets.css +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/static/css/tokens.css +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/static/css/variables.css +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/static/icons/heroicons.svg +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/static/js/htmx-config.js +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/storage/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/storage/base.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/storage/local.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/base.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/macros/icons.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/macros/table.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/2fa/setup.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/2fa/verify.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/audit_detail.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/audit_log.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/detail.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/list.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/profile/password.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/profile/profile.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/roles/form.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/roles/list.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/roles.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/settings/theme.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/pages/users/list.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/command_palette.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/flash_messages.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/inline_edit_form.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/pagination.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/templates/partials/sidebar.html +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/extra.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/views/list.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/widgets/__init__.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/widgets/base.py +0 -0
- {fastapi_admin_kit-0.1.2 → fastapi_admin_kit-0.2.1}/fastapi_admin_kit/widgets/resolver.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.1
|
|
3
|
+
Version: 0.2.1
|
|
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
|
|
@@ -25,23 +25,28 @@ Classifier: Typing :: Typed
|
|
|
25
25
|
Requires-Python: >=3.11
|
|
26
26
|
Requires-Dist: aiosqlite>=0.20.0
|
|
27
27
|
Requires-Dist: bcrypt>=4.0.0
|
|
28
|
-
Requires-Dist: fastapi>=0.
|
|
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'
|
|
37
|
+
Requires-Dist: pre-commit>=3.5.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: pyjwt>=2.13.0; extra == 'dev'
|
|
38
39
|
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
40
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
|
|
39
41
|
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
40
42
|
Requires-Dist: ruff>=0.5.0; extra == 'dev'
|
|
41
43
|
Provides-Extra: docs
|
|
42
44
|
Requires-Dist: mkdocs-material>=9.5.0; extra == 'docs'
|
|
43
45
|
Requires-Dist: mkdocs>=1.6.0; extra == 'docs'
|
|
44
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'
|
|
45
50
|
Provides-Extra: mysql
|
|
46
51
|
Requires-Dist: aiomysql>=0.2.0; extra == 'mysql'
|
|
47
52
|
Provides-Extra: postgres
|
|
@@ -55,53 +60,100 @@ Description-Content-Type: text/markdown
|
|
|
55
60
|
[](https://pypi.org/project/fastapi-admin-kit/)
|
|
56
61
|
[](https://pypi.org/project/fastapi-admin-kit/)
|
|
57
62
|
[](https://github.com/borhanst/fastapi-admin-kit/blob/main/LICENSE)
|
|
63
|
+
[](https://github.com/borhanst/fastapi-admin-kit/actions/workflows/tests.yml)
|
|
58
64
|
|
|
59
|
-
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.
|
|
60
66
|
|
|
61
|
-
|
|
67
|
+

|
|
62
68
|
|
|
63
69
|
📖 **[Documentation](https://borhanst.github.io/fastapi-admin-kit/)** | 🚀 **[Quick Start](#quick-start)** | 📦 **[PyPI](https://pypi.org/project/fastapi-admin-kit/)**
|
|
64
70
|
|
|
65
71
|
## Features
|
|
66
72
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
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
|
|
74
91
|
|
|
75
92
|
## Installation
|
|
76
93
|
|
|
77
94
|
```bash
|
|
95
|
+
# pip
|
|
78
96
|
pip install fastapi-admin-kit
|
|
97
|
+
|
|
98
|
+
# uv
|
|
99
|
+
uv add fastapi-admin-kit
|
|
79
100
|
```
|
|
80
101
|
|
|
81
102
|
For database-specific async drivers:
|
|
82
103
|
|
|
83
104
|
```bash
|
|
105
|
+
# pip
|
|
84
106
|
pip install fastapi-admin-kit[postgres] # PostgreSQL via asyncpg
|
|
85
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]
|
|
86
122
|
```
|
|
87
123
|
|
|
88
124
|
## Quick Start
|
|
89
125
|
|
|
90
126
|
```python
|
|
127
|
+
import os
|
|
128
|
+
import secrets
|
|
91
129
|
from contextlib import asynccontextmanager
|
|
130
|
+
|
|
92
131
|
from fastapi import FastAPI
|
|
93
132
|
from sqlalchemy import Column, Float, Integer, String
|
|
94
133
|
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
|
|
95
|
-
from sqlalchemy.orm import DeclarativeBase, sessionmaker
|
|
134
|
+
from sqlalchemy.orm import DeclarativeBase, relationship, sessionmaker
|
|
96
135
|
|
|
97
136
|
from fastapi_admin_kit import Admin
|
|
98
137
|
from fastapi_admin_kit.auth.backend import BuiltinAuthBackend
|
|
138
|
+
from fastapi_admin_kit.auth.mixins import AuthModelMixin
|
|
139
|
+
from fastapi_admin_kit.auth.models import Role, admin_user_roles
|
|
99
140
|
|
|
100
141
|
|
|
101
142
|
class Base(DeclarativeBase):
|
|
102
143
|
pass
|
|
103
144
|
|
|
104
145
|
|
|
146
|
+
class User(AuthModelMixin, Base):
|
|
147
|
+
__tablename__ = "users"
|
|
148
|
+
id = Column(Integer, primary_key=True)
|
|
149
|
+
email = Column(String(255), unique=True, nullable=False)
|
|
150
|
+
full_name = Column(String(255))
|
|
151
|
+
|
|
152
|
+
roles = relationship(
|
|
153
|
+
"Role", secondary=admin_user_roles, back_populates="users"
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
105
157
|
class Product(Base):
|
|
106
158
|
__tablename__ = "products"
|
|
107
159
|
id = Column(Integer, primary_key=True)
|
|
@@ -109,8 +161,8 @@ class Product(Base):
|
|
|
109
161
|
price = Column(Float, nullable=False)
|
|
110
162
|
|
|
111
163
|
|
|
112
|
-
DATABASE_URL = "sqlite+aiosqlite:///./app.db"
|
|
113
|
-
SECRET_KEY = "
|
|
164
|
+
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite+aiosqlite:///./app.db")
|
|
165
|
+
SECRET_KEY = os.getenv("SECRET_KEY", secrets.token_urlsafe(32))
|
|
114
166
|
|
|
115
167
|
engine = create_async_engine(DATABASE_URL)
|
|
116
168
|
async_session = sessionmaker(engine, class_=AsyncSession)
|
|
@@ -120,6 +172,7 @@ async_session = sessionmaker(engine, class_=AsyncSession)
|
|
|
120
172
|
async def lifespan(app: FastAPI):
|
|
121
173
|
async with engine.begin() as conn:
|
|
122
174
|
await conn.run_sync(Base.metadata.create_all)
|
|
175
|
+
await admin.setup()
|
|
123
176
|
yield
|
|
124
177
|
await engine.dispose()
|
|
125
178
|
|
|
@@ -130,11 +183,27 @@ admin = Admin(
|
|
|
130
183
|
engine=engine,
|
|
131
184
|
base=Base,
|
|
132
185
|
secret_key=SECRET_KEY,
|
|
186
|
+
auth_model=User,
|
|
133
187
|
auth_backend=BuiltinAuthBackend(),
|
|
134
188
|
)
|
|
135
189
|
admin.register(Product)
|
|
136
190
|
```
|
|
137
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
|
+
|
|
138
207
|
## CLI Usage
|
|
139
208
|
|
|
140
209
|
Both the full name and the short alias work interchangeably:
|
|
@@ -151,6 +220,13 @@ fak users
|
|
|
151
220
|
# Change a user's password
|
|
152
221
|
fak-admin changepassword -e admin@example.com -p newpassword
|
|
153
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
|
|
154
230
|
```
|
|
155
231
|
|
|
156
232
|
All commands accept `-d DATABASE_URL` or read the `DATABASE_URL` environment variable.
|
|
@@ -162,11 +238,14 @@ All commands accept `-d DATABASE_URL` or read the `DATABASE_URL` environment var
|
|
|
162
238
|
| Variable | Description | Default |
|
|
163
239
|
|---|---|---|
|
|
164
240
|
| `DATABASE_URL` | Async database connection string | `sqlite+aiosqlite:///./app.db` |
|
|
165
|
-
| `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 |
|
|
166
242
|
|
|
167
243
|
### Admin Options
|
|
168
244
|
|
|
169
245
|
```python
|
|
246
|
+
from fastapi_admin_kit import Admin
|
|
247
|
+
from fastapi_admin_kit.config import ThemeConfig
|
|
248
|
+
|
|
170
249
|
admin = Admin(
|
|
171
250
|
app=app,
|
|
172
251
|
engine=engine,
|
|
@@ -175,8 +254,6 @@ admin = Admin(
|
|
|
175
254
|
title="My Admin", # Admin panel title
|
|
176
255
|
admin_path="/admin", # URL prefix
|
|
177
256
|
dark_mode_default=False, # Dark mode on by default
|
|
178
|
-
# Theme
|
|
179
|
-
theme=ThemeConfig(preset="modern", primary_color="#6366F1"),
|
|
180
257
|
# Auth
|
|
181
258
|
auth_backend=BuiltinAuthBackend(),
|
|
182
259
|
# Environment badge
|
|
@@ -191,21 +268,42 @@ admin = Admin(
|
|
|
191
268
|
- **PostgreSQL**: `pip install fastapi-admin-kit[postgres]` + set `DATABASE_URL=postgresql+asyncpg://...`
|
|
192
269
|
- **MySQL**: `pip install fastapi-admin-kit[mysql]` + set `DATABASE_URL=mysql+aiomysql://...`
|
|
193
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
|
+
|
|
194
290
|
## Development
|
|
195
291
|
|
|
196
292
|
```bash
|
|
197
293
|
# Install with dev dependencies
|
|
198
|
-
|
|
294
|
+
uv sync
|
|
199
295
|
|
|
200
|
-
# Run tests
|
|
201
|
-
pytest
|
|
296
|
+
# Run tests with coverage
|
|
297
|
+
uv run pytest --cov=fastapi_admin_kit
|
|
202
298
|
|
|
203
299
|
# Lint
|
|
204
|
-
ruff check fastapi_admin_kit/
|
|
300
|
+
uv run ruff check fastapi_admin_kit/
|
|
301
|
+
|
|
302
|
+
# Format
|
|
303
|
+
uv run ruff format fastapi_admin_kit/
|
|
205
304
|
|
|
206
305
|
# Build distribution
|
|
207
|
-
|
|
208
|
-
hatch build
|
|
306
|
+
uv build
|
|
209
307
|
```
|
|
210
308
|
|
|
211
309
|
## License
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# FastAPI Admin Kit
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/fastapi-admin-kit/)
|
|
4
|
+
[](https://pypi.org/project/fastapi-admin-kit/)
|
|
5
|
+
[](https://github.com/borhanst/fastapi-admin-kit/blob/main/LICENSE)
|
|
6
|
+
[](https://github.com/borhanst/fastapi-admin-kit/actions/workflows/tests.yml)
|
|
7
|
+
|
|
8
|
+
A drop-in admin panel for FastAPI + SQLAlchemy + SQLModel apps, inspired by Django Unfold.
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
📖 **[Documentation](https://borhanst.github.io/fastapi-admin-kit/)** | 🚀 **[Quick Start](#quick-start)** | 📦 **[PyPI](https://pypi.org/project/fastapi-admin-kit/)**
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
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
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# pip
|
|
39
|
+
pip install fastapi-admin-kit
|
|
40
|
+
|
|
41
|
+
# uv
|
|
42
|
+
uv add fastapi-admin-kit
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
For database-specific async drivers:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# pip
|
|
49
|
+
pip install fastapi-admin-kit[postgres] # PostgreSQL via asyncpg
|
|
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]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Quick Start
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
import os
|
|
71
|
+
import secrets
|
|
72
|
+
from contextlib import asynccontextmanager
|
|
73
|
+
|
|
74
|
+
from fastapi import FastAPI
|
|
75
|
+
from sqlalchemy import Column, Float, Integer, String
|
|
76
|
+
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
|
|
77
|
+
from sqlalchemy.orm import DeclarativeBase, relationship, sessionmaker
|
|
78
|
+
|
|
79
|
+
from fastapi_admin_kit import Admin
|
|
80
|
+
from fastapi_admin_kit.auth.backend import BuiltinAuthBackend
|
|
81
|
+
from fastapi_admin_kit.auth.mixins import AuthModelMixin
|
|
82
|
+
from fastapi_admin_kit.auth.models import Role, admin_user_roles
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class Base(DeclarativeBase):
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class User(AuthModelMixin, Base):
|
|
90
|
+
__tablename__ = "users"
|
|
91
|
+
id = Column(Integer, primary_key=True)
|
|
92
|
+
email = Column(String(255), unique=True, nullable=False)
|
|
93
|
+
full_name = Column(String(255))
|
|
94
|
+
|
|
95
|
+
roles = relationship(
|
|
96
|
+
"Role", secondary=admin_user_roles, back_populates="users"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class Product(Base):
|
|
101
|
+
__tablename__ = "products"
|
|
102
|
+
id = Column(Integer, primary_key=True)
|
|
103
|
+
name = Column(String(100), nullable=False)
|
|
104
|
+
price = Column(Float, nullable=False)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite+aiosqlite:///./app.db")
|
|
108
|
+
SECRET_KEY = os.getenv("SECRET_KEY", secrets.token_urlsafe(32))
|
|
109
|
+
|
|
110
|
+
engine = create_async_engine(DATABASE_URL)
|
|
111
|
+
async_session = sessionmaker(engine, class_=AsyncSession)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@asynccontextmanager
|
|
115
|
+
async def lifespan(app: FastAPI):
|
|
116
|
+
async with engine.begin() as conn:
|
|
117
|
+
await conn.run_sync(Base.metadata.create_all)
|
|
118
|
+
await admin.setup()
|
|
119
|
+
yield
|
|
120
|
+
await engine.dispose()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
app = FastAPI(lifespan=lifespan)
|
|
124
|
+
admin = Admin(
|
|
125
|
+
app=app,
|
|
126
|
+
engine=engine,
|
|
127
|
+
base=Base,
|
|
128
|
+
secret_key=SECRET_KEY,
|
|
129
|
+
auth_model=User,
|
|
130
|
+
auth_backend=BuiltinAuthBackend(),
|
|
131
|
+
)
|
|
132
|
+
admin.register(Product)
|
|
133
|
+
```
|
|
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
|
+
|
|
150
|
+
## CLI Usage
|
|
151
|
+
|
|
152
|
+
Both the full name and the short alias work interchangeably:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# Create a superuser
|
|
156
|
+
fak-admin createsuperuser -e admin@example.com -p mypassword
|
|
157
|
+
fak createsuperuser -e admin@example.com -p mypassword # short alias
|
|
158
|
+
|
|
159
|
+
# List all admin users
|
|
160
|
+
fak-admin users
|
|
161
|
+
fak users
|
|
162
|
+
|
|
163
|
+
# Change a user's password
|
|
164
|
+
fak-admin changepassword -e admin@example.com -p newpassword
|
|
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
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
All commands accept `-d DATABASE_URL` or read the `DATABASE_URL` environment variable.
|
|
176
|
+
|
|
177
|
+
## Configuration
|
|
178
|
+
|
|
179
|
+
### Environment Variables
|
|
180
|
+
|
|
181
|
+
| Variable | Description | Default |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| `DATABASE_URL` | Async database connection string | `sqlite+aiosqlite:///./app.db` |
|
|
184
|
+
| `SECRET_KEY` | Signing key for sessions/CSRF/JWT (min 32 chars) | Auto-generated if unset |
|
|
185
|
+
|
|
186
|
+
### Admin Options
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from fastapi_admin_kit import Admin
|
|
190
|
+
from fastapi_admin_kit.config import ThemeConfig
|
|
191
|
+
|
|
192
|
+
admin = Admin(
|
|
193
|
+
app=app,
|
|
194
|
+
engine=engine,
|
|
195
|
+
base=Base,
|
|
196
|
+
secret_key=SECRET_KEY,
|
|
197
|
+
title="My Admin", # Admin panel title
|
|
198
|
+
admin_path="/admin", # URL prefix
|
|
199
|
+
dark_mode_default=False, # Dark mode on by default
|
|
200
|
+
# Auth
|
|
201
|
+
auth_backend=BuiltinAuthBackend(),
|
|
202
|
+
# Environment badge
|
|
203
|
+
environment_label="Production",
|
|
204
|
+
environment_color="danger",
|
|
205
|
+
)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Database Support
|
|
209
|
+
|
|
210
|
+
- **SQLite** (default, built-in via `aiosqlite`)
|
|
211
|
+
- **PostgreSQL**: `pip install fastapi-admin-kit[postgres]` + set `DATABASE_URL=postgresql+asyncpg://...`
|
|
212
|
+
- **MySQL**: `pip install fastapi-admin-kit[mysql]` + set `DATABASE_URL=mysql+aiomysql://...`
|
|
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
|
+
|
|
233
|
+
## Development
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Install with dev dependencies
|
|
237
|
+
uv sync
|
|
238
|
+
|
|
239
|
+
# Run tests with coverage
|
|
240
|
+
uv run pytest --cov=fastapi_admin_kit
|
|
241
|
+
|
|
242
|
+
# Lint
|
|
243
|
+
uv run ruff check fastapi_admin_kit/
|
|
244
|
+
|
|
245
|
+
# Format
|
|
246
|
+
uv run ruff format fastapi_admin_kit/
|
|
247
|
+
|
|
248
|
+
# Build distribution
|
|
249
|
+
uv build
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
MIT
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from fastapi_admin_kit.admin import Admin
|
|
4
4
|
from fastapi_admin_kit.admin.decorators import column
|
|
5
|
+
from fastapi_admin_kit.auth.mixins import AuthModelMixin
|
|
5
6
|
from fastapi_admin_kit.config import DatabaseConfig, DatabaseType
|
|
6
7
|
from fastapi_admin_kit.exceptions import ConfigError
|
|
7
8
|
from fastapi_admin_kit.nav import (
|
|
@@ -40,6 +41,7 @@ from fastapi_admin_kit.views import (
|
|
|
40
41
|
__all__ = [
|
|
41
42
|
"Admin",
|
|
42
43
|
"AdminRegistry",
|
|
44
|
+
"AuthModelMixin",
|
|
43
45
|
"ConfigError",
|
|
44
46
|
"DatabaseConfig",
|
|
45
47
|
"DatabaseType",
|
|
@@ -73,4 +75,4 @@ __all__ = [
|
|
|
73
75
|
# Per-model assets
|
|
74
76
|
"AdminExtra",
|
|
75
77
|
]
|
|
76
|
-
__version__ = "0.1
|
|
78
|
+
__version__ = "0.2.1"
|
|
@@ -36,9 +36,7 @@ class Action(ABC):
|
|
|
36
36
|
self.description = description
|
|
37
37
|
|
|
38
38
|
@abstractmethod
|
|
39
|
-
async def execute(
|
|
40
|
-
self, objects: list[Any], request: Request | None
|
|
41
|
-
) -> None:
|
|
39
|
+
async def execute(self, objects: list[Any], request: Request | None) -> None:
|
|
42
40
|
"""Run the action against the selected objects."""
|
|
43
41
|
...
|
|
44
42
|
|
|
@@ -58,9 +56,7 @@ class Action(ABC):
|
|
|
58
56
|
class ModelAction(Action):
|
|
59
57
|
"""Action that operates on a single model instance (row/detail actions)."""
|
|
60
58
|
|
|
61
|
-
async def execute_single(
|
|
62
|
-
self, obj: Any, request: Request | None
|
|
63
|
-
) -> None:
|
|
59
|
+
async def execute_single(self, obj: Any, request: Request | None) -> None:
|
|
64
60
|
"""Run the action on a single object.
|
|
65
61
|
|
|
66
62
|
Override this instead of execute for single-object actions.
|
|
@@ -19,9 +19,7 @@ class DeleteSelectedAction(Action):
|
|
|
19
19
|
confirmation_message="Are you sure you want to delete the selected items?",
|
|
20
20
|
)
|
|
21
21
|
|
|
22
|
-
async def execute(
|
|
23
|
-
self, objects: list[Any], request: Request | None
|
|
24
|
-
) -> None:
|
|
22
|
+
async def execute(self, objects: list[Any], request: Request | None) -> None:
|
|
25
23
|
# Actual deletion is handled by the existing bulk handler in views/factory.py
|
|
26
24
|
pass
|
|
27
25
|
|