Skip to content

Releases: vsdudakov/fastadmin

0.10.0

Choose a tag to compare

@vsdudakov vsdudakov released this 16 Jul 18:30

Features

  • Form field labels: list_display_labels now also applies to add/change form fields (and inline forms), not only list-page column headers. An explicit label in formfield_overrides widget props still wins.
  • Localization: the admin UI is fully translatable. Bundled languages: English, Russian, German, Spanish, French and Chinese. New ADMIN_LANGUAGE setting selects the default language (en by 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_color remains the accent everywhere.
  • antd deprecations fixed: Collapse expandIconPositionexpandIconPlacement, Transfer listStylestyles.section, Descriptions.Item JSX children / contentStyle → the items API with styles.content.
  • i18next is now registered via initReactI18next so components resolve translations (with interpolation) even outside an explicit I18nextProvider.

0.9.1

Choose a tag to compare

@vsdudakov vsdudakov released this 16 Jul 08:56

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 PasswordInput fields 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

Choose a tag to compare

@vsdudakov vsdudakov released this 16 Jul 07:29

Features

  • Column labels: new ModelAdmin.list_display_labels attribute ({"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 empty ids list and should treat it as "all objects".

Frontend

  • Apple-like design refresh: frosted-glass sticky header with hairline borders (the configured primary_color now serves as the accent instead of the header background), larger continuous corner radii, softer diffuse shadows, #f5f5f7/#161617 layout backgrounds, tighter letter spacing and transparent table headers. The rich-text editor accent follows primary_color instead 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-delta added to satisfy a peer dependency and baseUrl removed from tsconfig.json (deprecated in TypeScript 6).

Full Changelog: v0.8.3...v0.9.0

0.8.3

Choose a tag to compare

@vsdudakov vsdudakov released this 10 Jul 22:00
35d00a6

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 action endpoint now enforces permissions server-side via a new has_action_permission hook (defaults to has_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_KEY is 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 0 no longer misroutes a save (update vs insert) or is rejected as unauthenticated.
  • SQLAlchemy: get_model_pk_name resolves non-autoincrement primary keys (UUID/string) instead of falling back to "id"; contains/icontains filters cast to text so they work on integer columns; the primary key is excluded from required; and the generated primary key is read before commit so create/update is safe under the default expire_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 from required. 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 exclude and list_display now 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_LIMIT and ADMIN_SESSION_EXPIRED_AT fall 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

Choose a tag to compare

@vsdudakov vsdudakov released this 08 Jul 11:43
5f07c08

Bug-fix follow-up to the 0.8.1 audit. No public API changes.

Backend

  • SQLAlchemy: relationship (m2m) filter values are coerced to int for 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 NULL is expressible again on text columns via field__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 transformDataFromServer so every call site gets the safe behavior.

Full Changelog: v0.8.1...v0.8.2

0.8.1

Choose a tag to compare

@vsdudakov vsdudakov released this 07 Jul 07:42

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 to bool/None on 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 date key.
  • Stop corrupting text fields whose content looks like a date/time.
  • Render stored CheckboxGroup selections correctly.
  • Surface errors from dashboard action run/refresh.
  • Use the react-query v5 invalidateQueries signature to avoid over-invalidating unrelated queries.

Full Changelog: v0.8.0...v0.8.1

v0.8.0

Choose a tag to compare

@vsdudakov vsdudakov released this 05 Jul 13:49
c274620

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, an Enum's label, or a domain value object). Custom encoders take precedence over the built-in datetime/UUID/Decimal handling (#136, #138).

PyPI: https://pypi.org/project/fastadmin/0.8.0/

Full Changelog: v0.7.0...v0.8.0

v0.7.0

Choose a tag to compare

@vsdudakov vsdudakov released this 03 Jul 11:53
192b574

Yara ORM support

  • New YaraOrmModelAdmin / YaraOrmInlineModelAdmin admin classes and a fastadmin[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_yaraorm app; 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 test and CI now use -n auto.

Full changelog: https://github.com/vsdudakov/fastadmin/blob/main/CHANGELOG.md

v0.6.0

Choose a tag to compare

@vsdudakov vsdudakov released this 03 Jul 10:54
6624cc2

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_*_permission server-side on add/change/delete/export (previously UI-only).
  • Gate change_password so 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_AT to int (fixes a sign-in crash when set via env).

Medium / Low

  • Secure + SameSite=Lax session cookie (configurable).
  • Cap list/export limit via ADMIN_QUERY_MAX_LIMIT.
  • Stop returning internal exception text to clients.
  • Validate filter lookups and enforce the list_filter allowlist.
  • 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

Choose a tag to compare

@vsdudakov vsdudakov released this 03 Jul 09:45
9096aea

What's changed

  • Project restructure — PEP 621 pyproject.toml with the uv_build backend and a committed uv.lock (poetry removed).
  • New lint gateruff 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.md added, LICENSE renamed to LICENSE.md, README.md rewritten.
  • No changes to the public FastAdmin API.

Full changelog: https://github.com/vsdudakov/fastadmin/blob/main/CHANGELOG.md