Releases: vsdudakov/fastadmin
Release list
0.10.0
Features
- Form field labels:
list_display_labelsnow also applies to add/change form fields (and inline forms), not only list-page column headers. An explicitlabelinformfield_overrideswidget props still wins. - Localization: the admin UI is fully translatable. Bundled languages: English, Russian, German, Spanish, French and Chinese. New
ADMIN_LANGUAGEsetting selects the default language (enby default; set to empty to auto-detect from the browser). Users can switch the language from the header settings menu; the choice is persisted in the browser and also switches the Ant Design and dayjs locales (dates, pagination, pickers). - Theme modes: the header settings menu now offers Light, Dark and System themes. System (the default) follows the OS appearance live via
prefers-color-scheme.
Frontend
- Apple-like design polish: transparent macOS-style sidebar, frosted-glass dropdowns/popovers/pickers, blurred modal backdrop, overlay scrollbars, accent-tinted text selection, subtle table row hover and refined button radii. The configured
primary_colorremains the accent everywhere. - antd deprecations fixed:
Collapse expandIconPosition→expandIconPlacement,Transfer listStyle→styles.section,Descriptions.ItemJSX children /contentStyle→ theitemsAPI withstyles.content. - i18next is now registered via
initReactI18nextso components resolve translations (with interpolation) even outside an explicitI18nextProvider.
0.9.1
Security
- Passwords: saving a user from the change form no longer destroys the password by re-hashing the stored hash. The change form displayed the current hash in the read-only password field and echoed it back on Save, and the save hook hashed it again. The frontend now excludes
PasswordInputfields from the change payload, and the backend additionally drops a submitted password value that matches the stored one, so third-party clients that echo the hash are also safe. Passwords are changed only via the change-password endpoint / modal.
0.9.0
Features
- Column labels: new
ModelAdmin.list_display_labelsattribute ({"field": "Header"}) overrides or translates auto-generated list-page column titles. Sorting, filtering and data binding stay keyed by the field name. - Actions without selection:
@action(requires_selection=False)enables the Apply button without selecting rows; the action receives an emptyidslist and should treat it as "all objects".
Frontend
- Apple-like design refresh: frosted-glass sticky header with hairline borders (the configured
primary_colornow serves as the accent instead of the header background), larger continuous corner radii, softer diffuse shadows,#f5f5f7/#161617layout backgrounds, tighter letter spacing and transparent table headers. The rich-text editor accent followsprimary_colorinstead of a hardcoded teal. - Dependencies: antd 6.5.1, i18next 26, react-i18next 17, vite 8, jsdom 29, TypeScript 6.0, vitest 4.1.10, eslint 10.7;
quill-deltaadded to satisfy a peer dependency andbaseUrlremoved fromtsconfig.json(deprecated in TypeScript 6).
Full Changelog: v0.8.3...v0.9.0
0.8.3
Correctness and security fixes from a full-codebase review. The only public API addition is the backward-compatible has_action_permission model-admin hook.
Security
- Actions: the
actionendpoint now enforces permissions server-side via a newhas_action_permissionhook (defaults tohas_change_permission), so a read-only admin can no longer run a registered bulk action. Override the hook to allow a read-only user to run a specific non-mutating action. - Passwords: editing a user with an empty password field no longer overwrites the stored hash with a hash of the empty string.
- JWT: signing and verifying are refused when
ADMIN_SECRET_KEYis unset or empty, closing an empty-secret token-forgery path and returning a clear configuration error instead of an HTTP 500.
Backend
- All ORMs: a legitimate primary key / user id of
0no longer misroutes a save (update vs insert) or is rejected as unauthenticated. - SQLAlchemy:
get_model_pk_nameresolves non-autoincrement primary keys (UUID/string) instead of falling back to"id";contains/icontainsfilters cast to text so they work on integer columns; the primary key is excluded fromrequired; and the generated primary key is read before commit so create/update is safe under the defaultexpire_on_commit=True. - Tortoise / Django / Yara: a falsy database default (
0/False/"") no longer marks a field as required, and the primary key is excluded fromrequired. Tortoise enum options now emit the scalar value, and Django choice options no longer swap the stored value with the human-readable label. - Serialization: a field listed in both
excludeandlist_displaynow stays excluded from API responses. - Validation: malformed date/datetime values, empty-condition filters (
field__), unsupported or null export formats, and malformed request bodies on the Django integration now return HTTP 422 instead of an unhandled 500. - Settings:
ADMIN_QUERY_MAX_LIMITandADMIN_SESSION_EXPIRED_ATfall back to their defaults on a blank or non-numeric value instead of crashing the package at import.
Full Changelog: v0.8.2...v0.8.3
0.8.2
Bug-fix follow-up to the 0.8.1 audit. No public API changes.
Backend
- SQLAlchemy: relationship (m2m) filter values are coerced to
intfor integer primary keys (previously raised HTTP 500 on strictly typed drivers such as PostgreSQL/asyncpg), and unsupported lookups on relation fields (e.g.icontains) are rejected with HTTP 422 instead of silently matching by primary-key equality. - Pony ORM: the foreign-key filter rewrite no longer corrupts filters on plain columns whose name merely ends with
_id, and list-view search now runs as a single OR'd WHERE clause instead of materializing every matching row once per search field. - Flask:
HTTPExceptions with an attached response (abort(Response(...))) are passed through unchanged, error headers (Allow,WWW-Authenticate,Retry-After, ...) are preserved on JSON error responses, and unhandled errors are logged with their traceback. - Filtering:
IS NULLis expressible again on text columns viafield__exact=null(substring lookups keep the literal string"null").
Frontend
- Stop corrupting text fields whose content is the literal word
"true"/"false"on the change form (booleans are now only coerced for boolean widgets). - Stop shape-based date detection for fields known to have no date widget.
- Pass the model configuration directly to
transformDataFromServerso every call site gets the safe behavior.
Full Changelog: v0.8.1...v0.8.2
0.8.1
Bug-fix release from a full-source audit of main. No public API changes.
Backend
- Pony ORM: fix list-view search crashing (HTTP 500) for models whose primary key is not named
id, and fix multi-field ordering with mixed ascending/descending fields silently sorting by the wrong priority. - SQLAlchemy: filtering a list by a many-to-many (or other relationship) field no longer raises an unhandled 500; it now matches on the related row's primary key.
- Flask: unhandled server errors now return a proper HTTP 500 with a generic message (previously sent as HTTP 200 and leaked the exception text), and API errors are returned as JSON
{"detail": ...}matching the Django/FastAPI integrations instead of HTML error pages. - Filtering: the literal strings
"true","false", and"null"are no longer coerced tobool/Noneon text fields, so a text column can be filtered for those exact values.
Frontend
- Fix a form-save crash when a JSON field value is an object with a
datekey. - Stop corrupting text fields whose content looks like a date/time.
- Render stored
CheckboxGroupselections correctly. - Surface errors from dashboard action run/refresh.
- Use the react-query v5
invalidateQueriessignature to avoid over-invalidating unrelated queries.
Full Changelog: v0.8.0...v0.8.1
v0.8.0
0.8.0
- Add a
register_encoder(type_, encoder)hook to control how a type is serialized in every admin API response (e.g. a custom datetime format, anEnum's label, or a domain value object). Custom encoders take precedence over the built-indatetime/UUID/Decimalhandling (#136, #138).
PyPI: https://pypi.org/project/fastadmin/0.8.0/
Full Changelog: v0.7.0...v0.8.0
v0.7.0
Yara ORM support
- New
YaraOrmModelAdmin/YaraOrmInlineModelAdminadmin classes and afastadmin[yara-orm]extra for Yara ORM — a fast, async Python ORM with a Rust engine. - Full model introspection and CRUD (foreign keys, one-to-one, many-to-many), mirroring the other ORM adapters.
- Runnable
examples/fastapi_yaraormapp; docs, README, API reference and the install matrix updated.
Action results
- Add a refresh button to the widget action results toolbar and the expand modal, so results can be re-run in place without losing scroll position (#132).
Tests
- Run the suite in parallel (
pytest -n auto): per-xdist-worker SQLite files with a busy timeout fix the Django/Pony "database is locked" errors.make testand CI now use-n auto.
Full changelog: https://github.com/vsdudakov/fastadmin/blob/main/CHANGELOG.md
v0.6.0
Security hardening release. No changes to the documented public API, but several defaults are now stricter — see the upgrade note below.
Critical / High
- Enforce
has_*_permissionserver-side on add/change/delete/export (previously UI-only). - Gate
change_passwordso a signed-in user cannot reset another user's password. - Restrict form saves to
fields/exclude/readonly_fields(mass-assignment protection); hash passwords on edit as well as create. - Parameterize Pony ORM filters/search (were built from f-strings).
- Neutralize CSV formula injection in exports.
- Coerce
ADMIN_SESSION_EXPIRED_ATto int (fixes a sign-in crash when set via env).
Medium / Low
Secure+SameSite=Laxsession cookie (configurable).- Cap list/export
limitviaADMIN_QUERY_MAX_LIMIT. - Stop returning internal exception text to clients.
- Validate filter lookups and enforce the
list_filterallowlist. - Column-based SQLAlchemy ordering (no raw
text()); escape LIKE/ILIKE wildcards. - Unify CSV/JSON export columns; dead-code cleanup.
- Frontend: reject
javascript:/data:URIs in file and view-on-site links.
New settings
ADMIN_SESSION_COOKIE_SECURE, ADMIN_SESSION_COOKIE_SAMESITE, ADMIN_QUERY_MAX_LIMIT.
Upgrade note
For local HTTP development set ADMIN_SESSION_COOKIE_SECURE=false, and set list_filter/fields where you relied on filtering arbitrary columns.
Full changelog: https://github.com/vsdudakov/fastadmin/blob/main/CHANGELOG.md
v0.5.0
What's changed
- Project restructure — PEP 621
pyproject.tomlwith theuv_buildbackend and a committeduv.lock(poetry removed). - New lint gate —
ruff check+ruff format+ty(replacing black/isort/mypy). - New documentation site — MkDocs Material, deployed to GitHub Pages: https://vsdudakov.github.io/fastadmin/
- New workflows — CI (lint, backend test matrix, frontend, per-extras install checks), docs deploy, and this tag-driven PyPI release.
- Dependency upgrades — all backend and frontend packages bumped (antd 6.5, eslint 10.6, vitest 4.1); frontend rebuilt.
CHANGELOG.mdadded,LICENSErenamed toLICENSE.md,README.mdrewritten.- No changes to the public FastAdmin API.
Full changelog: https://github.com/vsdudakov/fastadmin/blob/main/CHANGELOG.md