### Install and Run Flask SQLAlchemy Example Source: https://github.com/vsdudakov/fastadmin/blob/main/examples/flask_sqlalchemy/README.md Use 'make install' to set up the virtual environment with Poetry. 'make run' will initialize the database, create a superuser, and start the Flask development server on port 8090. ```bash make install # Create virtualenv with Poetry make run # Run init_db + create_superuser, then start Flask on port 8090 ``` -------------------------------- ### Development Environment Setup Source: https://github.com/vsdudakov/fastadmin/blob/main/frontend/README.md Steps to set up the development environment, including installing dependencies and starting the dev server. Requires a running FastAdmin backend. ```bash yarn yarn dev ``` -------------------------------- ### Install and Run Django Development Server Source: https://github.com/vsdudakov/fastadmin/blob/main/examples/django_djangoorm/README.md Commands to install dependencies using Poetry and start the Django development server. ```bash make install # Create virtualenv with Poetry make run # Start the Django dev server ``` -------------------------------- ### Install and Run FastAPI with Tortoise ORM Source: https://github.com/vsdudakov/fastadmin/blob/main/examples/fastapi_tortoiseorm/README.md Use these commands to install dependencies and start the FastAPI development server. Access the admin interface at http://127.0.0.1:8090/admin/. ```bash make install # Create virtualenv with Poetry ``` ```bash make run # Start the FastAPI dev server ``` -------------------------------- ### Start Development Server Source: https://github.com/vsdudakov/fastadmin/blob/main/frontend/README.md Starts the Vite development server for local development. Ensure the FastAdmin backend is running and accessible. ```bash yarn dev ``` -------------------------------- ### FastAPI Application Setup Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Initializes a FastAPI application with the defined lifespan and mounts the FastAdmin application at the '/admin' path. ```python app = FastAPI(lifespan=lifespan) app.mount("/admin", admin_app) ``` -------------------------------- ### Install FastAdmin with Poetry Source: https://github.com/vsdudakov/fastadmin/blob/main/README.md Install FastAdmin with specific framework and ORM support using Poetry. For zsh and macOS, use quotes around the package name. ```bash poetry add 'fastadmin[fastapi,django]' poetry add 'fastadmin[fastapi,tortoise-orm]' poetry add 'fastadmin[fastapi,pony]' poetry add 'fastadmin[fastapi,sqlalchemy]' poetry add 'fastadmin[django]' poetry add 'fastadmin[django,pony]' poetry add 'fastadmin[flask,sqlalchemy]' ``` -------------------------------- ### Install Dependencies Source: https://github.com/vsdudakov/fastadmin/blob/main/frontend/README.md Installs project dependencies using Yarn. Ensure Node.js 18+ and Yarn are installed. ```bash yarn ``` -------------------------------- ### FastAdmin Settings Class Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Example Python class demonstrating FastAdmin settings configuration using environment variables. ```python class Settings: """Settings""" # This value is the prefix you used for mounting FastAdmin app for FastAPI. ADMIN_PREFIX: str = os.getenv("ADMIN_PREFIX", "admin") # This value is the site name on sign-in page and on header. ADMIN_SITE_NAME: str = os.getenv("ADMIN_SITE_NAME", "FastAdmin") # This value is the logo path on sign-in page. ADMIN_SITE_SIGN_IN_LOGO: str = os.getenv("ADMIN_SITE_SIGN_IN_LOGO", "/admin/static/images/sign-in-logo.svg") # This value is the logo path on header. ADMIN_SITE_HEADER_LOGO: str = os.getenv("ADMIN_SITE_HEADER_LOGO", "/admin/static/images/header-logo.svg") # This value is the favicon path. ADMIN_SITE_FAVICON: str = os.getenv("ADMIN_SITE_FAVICON", "/admin/static/images/favicon.png") # This value is the primary color for FastAdmin. ADMIN_PRIMARY_COLOR: str = os.getenv("ADMIN_PRIMARY_COLOR", "#009485") # This value is the session id key to store session id in http only cookies. ADMIN_SESSION_ID_KEY: str = os.getenv("ADMIN_SESSION_ID_KEY", "admin_session_id") # This value is the expired_at period (in sec) for session id. ADMIN_SESSION_EXPIRED_AT: int = os.getenv("ADMIN_SESSION_EXPIRED_AT", 144000) # in sec # This value is the date format for JS widgets. ADMIN_DATE_FORMAT: str = os.getenv("ADMIN_DATE_FORMAT", "YYYY-MM-DD") # This value is the datetime format for JS widgets. ADMIN_DATETIME_FORMAT: str = os.getenv("ADMIN_DATETIME_FORMAT", "YYYY-MM-DD HH:mm") # This value is the time format for JS widgets. ADMIN_TIME_FORMAT: str = os.getenv("ADMIN_TIME_FORMAT", "HH:mm:ss") # This value is the name for User db/orm model class for authentication. ADMIN_USER_MODEL: str = os.getenv("ADMIN_USER_MODEL") # This value is the username field for User db/orm model for for authentication. ADMIN_USER_MODEL_USERNAME_FIELD: str = os.getenv("ADMIN_USER_MODEL_USERNAME_FIELD") # This value is the key to securing signed data - it is vital you keep this secure, # or attackers could use it to generate their own signed values. ADMIN_SECRET_KEY: str = os.getenv("ADMIN_SECRET_KEY") ``` -------------------------------- ### Install FastAdmin with Poetry Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Add FastAdmin with optional dependencies for FastAPI and Django ORM using Poetry. ```bash poetry add 'fastadmin[fastapi,django]' ``` -------------------------------- ### Model Admin Class with Actions and Display Methods Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Example of a Python model admin class defining custom actions like 'make_is_active' and 'make_is_not_active', and display methods like 'started' and 'name_with_price'. ```python e event active") def make_is_active(self, ids): self.model_cls.objects.filter(id__in=ids).update(is_active=True) @action def make_is_not_active(self, ids): self.model_cls.objects.filter(id__in=ids).update(is_active=False) @display def started(self, obj): return bool(obj.start_time) @display() def name_with_price(self, obj): return f"{obj.name} - {obj.price}" ``` -------------------------------- ### Install FastAdmin with Pip Source: https://github.com/vsdudakov/fastadmin/blob/main/README.md Install FastAdmin with specific framework and ORM support using pip. For zsh and macOS, use quotes around the package name. ```bash pip install fastadmin[fastapi,django] # FastAPI with Django ORM pip install fastadmin[fastapi,tortoise-orm] # FastAPI with Tortoise ORM pip install fastadmin[fastapi,pony] # FastAPI with Pony ORM pip install fastadmin[fastapi,sqlalchemy] # FastAPI with SQLAlchemy (includes greenlet) pip install fastadmin[django] # Django with Django ORM pip install fastadmin[django,pony] # Django with Pony ORM pip install fastadmin[flask,sqlalchemy] # Flask with SQLAlchemy (includes greenlet) ``` -------------------------------- ### Display Event Start Time Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html A display function for an admin interface that returns a boolean indicating if the event has a start time. ```python return bool(obj.start_time) ``` -------------------------------- ### FastAPI Application Setup with Lifespan and Admin Mount Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Configures a FastAPI application, including database initialization via Tortoise ORM during lifespan events and mounting the admin interface. ```python async def create_superuser(): await User.create( username="admin", password="admin", is_superuser=True, ) @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: # RegisterTortoise sets up TortoiseContext so request handlers can use the DB # (_enable_global_fallback=True by default for ASGI lifespan in a background task) async with RegisterTortoise( app=app, db_url="sqlite://:memory:", modules={"models": ["models"]}, generate_schemas=True, use_tz=False, timezone="UTC", ): await create_superuser() yield app = FastAPI(lifespan=lifespan) app.mount("/admin", admin_app) ``` -------------------------------- ### Event Model Display Methods Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Custom display methods for the Event model. 'started' returns a boolean indicating if the start_time is set, and 'name_with_price' formats the name and price into a string. ```python @display async def started(self, obj): return bool(obj.start_time) @display() async def name_with_price(self, obj): return f"{obj.name} - {obj.price}" ``` -------------------------------- ### FastAPI Admin Setup and User Model Configuration Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Sets up environment variables for user model configuration and imports necessary components from FastAPI and FastAdmin. It then defines a UserModelAdmin class to configure the admin interface for the User model. ```python import os import uuid from collections.abc import AsyncGenerator from contextlib import asynccontextmanager os.environ["ADMIN_USER_MODEL"] = "User" os.environ["ADMIN_USER_MODEL_USERNAME_FIELD"] = "username" os.environ["ADMIN_SECRET_KEY"] = "secret" from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from models import Base, BaseEvent, Event, Tournament, User, sqlalchemy_engine, sqlalchemy_sessionmaker from sqlalchemy import select, update from fastadmin import ( SqlAlchemyInlineModelAdmin, SqlAlchemyModelAdmin, WidgetActionArgumentProps, WidgetActionChartProps, WidgetActionFilter, WidgetActionInputSchema, WidgetActionParentArgumentProps, WidgetActionProps, WidgetActionResponseSchema, WidgetActionType, WidgetType, action, display, ) from fastadmin import fastapi_app as admin_app from fastadmin import ( register, widget_action, ) @register(User, sqlalchemy_sessionmaker=sqlalchemy_sessionmaker) class UserModelAdmin(SqlAlchemyModelAdmin): menu_section = "Users" list_display = ("id", "username", "is_superuser") list_display_links = ("id", "username") list_filter = ("id", "username", "is_superuser") search_fields = ("username",) formfield_overrides = { "username": (WidgetType.SlugInput, {"required": True}), "password": (WidgetType.PasswordInput, {"passwordModalForm": True}), "avatar_url": ( WidgetType.UploadImage, { "required": False, }, ), "attachment_url": ( WidgetType.UploadFile, {"required": True}, ), } widget_actions = ( "sales_chart", "sales_area_chart", "sales_column_chart", "sales_bar_chart", "sales_pie_chart", "sales_action", ) async def authenticate(self, username: str, password: str) -> uuid.UUID | int | None: sessionmaker = self.get_sessionmaker() async with sessionmaker() as session: query = select(self.model_cls).filter_by(username=username, password=password, is_superuser=True) result = await session.scalars(query) obj = result.first() if not obj: return None return obj.id async def change_password(self, id: uuid.UUID | int, password: str) -> None: sessionmaker = self.get_sessionmaker() async with sessionmaker() as session: query = update(self.model_cls).where(User.id.in_([id])).values(password=password) await session.execute(query) await session.commit() async def upload_file( self, field_name: str, file_name: str, file_content: bytes, obj: Base | None = None, ) -> str: """This method is used to upload files. :params field_name: a name of field. :params file_name: a name of file. :params file_content: a content of file. :params obj: the existing ORM model instance when uploading on the change page, or None when on the add page. :return: A file url. """ return f"https://fastadmin.io/media/{file_name}" async def pre_generate_models_schema(self) -> None: sessionmaker = self.get_sessionmaker() async with sessionmaker() as session: result = await session.execute(select(self.model_cls.username)) options = list(result.scalars().all()) widget_action_props: WidgetActionProps = self.__class__.sales_action.widget_action_props for argument in widget_action_props.arguments: if argument.name == "username": argument.widget_props["options"] = [{"label": option, "value": option} for option in options] break @widget_action( widget_action_type=WidgetActionType.ChartLine, widget_action_props=WidgetActionChartProps( x_field="x", y_field="y", series_field="series", series_color={ "Sales": "#1677ff", "Sales 2": "#52c41a", }, ), widget_action_filters=[ WidgetActionFilter( ``` -------------------------------- ### Registering Dashboard Widget Actions Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Example of registering a line chart widget for displaying user analytics over time. Ensure the widget action method name is listed in the widget_actions attribute. ```python from fastadmin import TortoiseModelAdmin, widget_action from fastadmin.models.schemas import ( WidgetActionChartProps, WidgetActionInputSchema, WidgetActionResponseSchema, WidgetActionType, ) class UserAdmin(TortoiseModelAdmin): # Register widgets by method name widget_actions = ("users_chart",) @widget_action( widget_action_type=WidgetActionType.ChartLine, widget_action_props=WidgetActionChartProps(x_field="x", y_field="y"), tab="Analytics", title="Users over time", ) async def users_chart(self, payload: WidgetActionInputSchema) -> WidgetActionResponseSchema: # Build and return data for the chart return WidgetActionResponseSchema( data=[ {"x": "2026-01-01", "y": 10}, {"x": "2026-01-02", "y": 15}, ], ) ``` -------------------------------- ### Example Usage of @widget_action Decorator Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Demonstrates how to use the @widget_action decorator with various parameters to define a sales chart widget. This includes setting the tab, title, description, chart properties, and filters. ```python def widget_action( function=None, *, tab: str = "Default", sub_tab: str | None = None, title: str = "Action", description: str | None = None, widget_action_type: WidgetActionType = WidgetActionType.Action, widget_action_props: WidgetActionChartProps | WidgetActionProps | None = None, widget_action_filters: list[WidgetActionFilter] | None = None, width: ( tp.Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] | None ) = None, # width in 1-24 grid system max_height: int | None = None, ): """Conveniently add attributes to a widget action function: Example of usage: @widget_action( tab="Default", title="Action", description="Chart of total sales by status", widget_action_type=WidgetActionType.Action, widget_action_props=WidgetActionChartProps( x_field="date", y_field="total_sales", series_field="status", ), widget_action_filters=[ WidgetActionFilter( field_name="status", widget_type=WidgetType.Select, widget_props={ "mode": "multiple", "options": [ { "label": "Pending", "value": "Pending", }, { "label": "Completed", "value": "Completed", }, ], }, ) ], ) async def sales_chart(self, payload: WidgetActionInputSchema) -> WidgetActionResponseSchema: # filter by payload.query return WidgetActionResponseSchema( data=[ { "date": "2026-01-01", "total_sales": 100, "status": "Pending", }, { "date": "2026-01-02", "total_sales": 200, "status": "Completed", }, ], ) :param function: A function to decorate. :param description: A string value to set the function's short_description """ def decorator(func): wrapped = _wrap_callable(func) wrapped.is_widget_action = True wrapped.widget_action_type = widget_action_type wrapped.widget_action_props = widget_action_props wrapped.widget_action_filters = widget_action_filters wrapped.tab = tab wrapped.sub_tab = sub_tab wrapped.title = title wrapped.width = width wrapped.max_height = max_height if description is not None: wrapped.short_description = description return wrapped if function is None: return decorator return decorator(function) ``` -------------------------------- ### FastAPI Application Setup with Admin and CORS Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Initializes a FastAPI application, mounts the admin interface at '/admin', and configures CORS middleware to allow requests from specified origins. This sets up the basic structure for a web application with an admin panel and cross-origin request handling. ```python app = FastAPI(lifespan=lifespan) app.mount("/admin", admin_app) app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3030", "http://localhost:8090"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) ``` -------------------------------- ### Get Sales Data Action Widget Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Implements an action widget to retrieve sales data. Demonstrates using AsyncSelect, Select with dynamic options, and conditional arguments based on parent values. ```python async def sales_action(self, payload: WidgetActionInputSchema) -> WidgetActionResponseSchema: return WidgetActionResponseSchema( data=[ { "id": 1, "name": "Sales", }, { "id": 2, "name": "Sales", }, { "id": 3, "name": "Sales", }, ], ) ``` -------------------------------- ### Tournament Data Action Widget Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Defines an action widget to fetch tournament data. This is a basic setup for an action type widget. ```python @widget_action( widget_action_type=WidgetActionType.Action, tab="Data", title="Get tournament data", description="Get tournament data", width ``` -------------------------------- ### Registering Inlines Example Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Demonstrates how to register inline models for Tortoise ORM admin interfaces. This is used to embed related model administration within another model's admin page. ```python class EventInlineModelAdmin(TortoiseInlineModelAdmin): model = Event ``` -------------------------------- ### Build Documentation from Project Root Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/README.md Navigate to the docs directory and use the make build command to generate the documentation site and README. ```bash cd docs make build ``` -------------------------------- ### Build Documentation using Poetry and Python Script Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/README.md Alternatively, use poetry to run the build.py script for generating documentation from the project root. ```bash cd docs && poetry run python build.py ``` -------------------------------- ### Preview Production Build Source: https://github.com/vsdudakov/fastadmin/blob/main/frontend/README.md Serves the production build locally for previewing. ```bash yarn preview ``` -------------------------------- ### Initialize Database and Create Superuser Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Set up an in-memory SQLite database for testing and create a default superuser. The `lifespan` context manager ensures these are executed on application startup. ```python def init_db(): # Use shared in-memory sqlite DB so tables are visible across connections/threads. db.bind(provider="sqlite", filename=":sharedmemory:", create_db=True) db.generate_mapping(create_tables=True) @db_session def create_superuser(): User( username="admin", password="admin", is_superuser=True, attachment_url="/media/attachment.txt", ) ``` -------------------------------- ### Get File URL Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Generates a display URL for an uploaded file field. ```APIDOC ## GET /files/{field_name}/{value} ### Description Returns the display URL for an uploaded file field. This is called during serialization for upload fields. ### Method GET ### Endpoint /files/{field_name}/{value} ### Parameters #### Path Parameters - **field_name** (str) - Required - The name of the upload field. - **value** (str) - Required - The raw stored value of the file (e.g., "s3://bucket/key" or "/media/file.pdf"). ### Response #### Success Response (200) - **url** (str) - The URL string to expose to the frontend for display or download. ### Response Example ```json { "url": "https://example.com/path/to/file.pdf" } ``` ``` -------------------------------- ### Get Object by ID Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Retrieves a single serialized object based on its unique identifier. ```APIDOC ## GET /objects/{id} ### Description Retrieves a serialized object by its unique ID. ### Method GET ### Endpoint /objects/{id} ### Parameters #### Path Parameters - **id** (UUID | int | str) - Required - The ID of the object to retrieve. ### Response #### Success Response (200) - **object** (dict) - A dictionary representing the serialized object, or null if not found. ### Response Example ```json { "id": "123e4567-e89b-12d3-a456-426614174000", "field1": "value1", "field2": "value2" } ``` ``` -------------------------------- ### Database Initialization and Superuser Creation Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Provides functions for initializing the database by dropping and creating all tables, and for creating a default superuser with specified credentials. These are used within the application's lifespan context. ```python async def init_db(): async with sqlalchemy_engine.begin() as c: await c.run_sync(Base.metadata.drop_all) await c.run_sync(Base.metadata.create_all) async def create_superuser(): async with sqlalchemy_sessionmaker() as s: user = User( username="admin", password="admin", is_superuser=True, attachment_url="/media/attachment.txt", ) s.add(user) await s.commit() ``` -------------------------------- ### Get List of Serialized Objects Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Retrieves a paginated and searchable list of serialized objects. Supports filtering and sorting. ```APIDOC ## GET /objects ### Description Retrieves a list of serialized objects with support for pagination, searching, sorting, and filtering. ### Method GET ### Endpoint /objects ### Parameters #### Query Parameters - **offset** (int) - Optional - An offset for pagination. - **limit** (int) - Optional - A limit for pagination. - **search** (str) - Optional - A search query. - **sort_by** (str) - Optional - A field name to sort by. - **filters** (dict) - Optional - A dictionary of filters. ### Response #### Success Response (200) - **serialized_objs** (list[dict]) - A list of serialized objects. - **total** (int) - The total count of objects available. ### Response Example ```json { "serialized_objs": [ { "field1": "value1", "field2": "value2" }, { "field1": "value3", "field2": "value4" } ], "total": 100 } ``` ``` -------------------------------- ### Initialize PonyORM Database and Generate Mapping Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Set up the PonyORM database connection and generate the necessary tables. This function should be called before any database operations. ```python def init_db(): # Use shared in-memory sqlite DB so tables are visible across connections/threads. db.bind(provider="sqlite", filename=":sharedmemory:", create_db=True) db.generate_mapping(create_tables=True) ``` -------------------------------- ### Get Serialized Object by ID Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Retrieves a single serialized object based on its unique identifier. Returns None if the object is not found. ```python async def get_obj(self, id: UUID | int | str) -> dict | None: """This method is used to get serialized object by id. :params id: an id of object. :return: A dict or None. """ obj = await self.orm_get_obj(id) if not obj: return None return await self.serialize_obj(obj) ``` -------------------------------- ### Initialize Database Schema Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Asynchronous function to initialize the database by dropping and creating all tables based on the metadata. ```python async def init_db(): async with sqlalchemy_engine.begin() as c: await c.run_sync(Base.metadata.drop_all) await c.run_sync(Base.metadata.create_all) ``` -------------------------------- ### ORM Get List of Objects Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Asynchronous method to retrieve a paginated list of ORM objects. Supports searching, sorting, and filtering. ```python async def orm_get_list( self, offset: int | None = None, limit: int | None = None, search: str | None = None, sort_by: str | None = None, filters: dict | None = None, ) -> tuple[list[Any], int]: """This method is used to get list of orm/db model objects. :params offset: an offset for pagination. :params limit: a limit for pagination. :params search: a search query. :params sort_by: a sort by field name. :params filters: a dict of filters. :return: A tuple of list of objects and total count. """ raise NotImplementedError ``` -------------------------------- ### Build for Production Source: https://github.com/vsdudakov/fastadmin/blob/main/frontend/README.md Performs a type check and creates a production build. The output is placed in the parent package's static folder as UMD modules. ```bash yarn build ``` -------------------------------- ### Get List of Serialized Objects Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Retrieves a paginated and searchable list of serialized objects along with the total count. Supports sorting and filtering. ```python async def get_list(self, offset: int | None = None, limit: int | None = None, search: str | None = None, sort_by: str | None = None, filters: dict | None = None, ) -> tuple[list[dict], int]: """This method is used to get list of seriaized objects. :params offset: an offset for pagination. :params limit: a limit for pagination. :params search: a search query. :params sort_by: a sort by field name. :params filters: a dict of filters. :return: A tuple of list of dict and total count. """ resolved_sort_by = self.resolve_sort_by(sort_by) if sort_by else None objs, total = await self.orm_get_list( offset=offset, limit=limit, search=search, sort_by=resolved_sort_by, filters=filters, ) serialized_objs = [] for obj in objs: serialized_objs.append(await self.serialize_obj(obj, list_view=True)) return serialized_objs, total ``` -------------------------------- ### Get Fields for Serialization Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Retrieves a set of field names that are eligible for serialization. This considers fields defined with widget types and applies inclusions/exclusions. ```python def get_fields_for_serialize(self) -> set[str]: """This method is used to get fields for serialize. :return: A set of fields. """ fields = self.get_model_fields_with_widget_types() fields_for_serialize = {field.name for field in fields} if self.fields: fields_for_serialize &= set(self.fields) if self.exclude: fields_for_serialize -= set(self.exclu) ``` -------------------------------- ### Run Tests Source: https://github.com/vsdudakov/fastadmin/blob/main/frontend/README.md Executes the test suite using Vitest. ```bash yarn test ``` -------------------------------- ### Get SQLAlchemy Session Maker Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Class method to retrieve the database session maker, specifically for SQLAlchemy. This is used to create new database sessions. ```python @classmethod def get_sessionmaker(cls) -> Any: """This method is used to get db session maker for sqlalchemy. :return: A db session maker. """ return cls.db_session_maker ``` -------------------------------- ### ORM Get Object by ID Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Asynchronous method to retrieve a single ORM object by its ID. Returns the object if found, otherwise returns None. ```python async def orm_get_obj(self, id: UUID | int | str) -> Any | None: """This method is used to get orm/db model object. :params id: an id of object. :return: An object or None. """ raise NotImplementedError ``` -------------------------------- ### FastAdmin Class Initialization Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Initializes the FastAdmin class with a model class and sets up context variables for request and user. ```python def __init__(self, model_cls: Any): """Initialize admin class. :params model_cls: an orm/db model class. """ self.model_cls = model_cls self._request_context = ContextVar(f"fastadmin_admin_request_context_{id(self)}", default=None) self._user_context = ContextVar(f"fastadmin_admin_user_context_{id(self)}", default=None) ``` -------------------------------- ### Get Current Request Object Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Retrieves the current request object from the asynchronous context. This is useful for accessing request-specific information within the current task. ```python @property def request(self) -> Any | None: """Current request object for this async context.""" return self._request_context.get() ``` -------------------------------- ### Get Tournament Data Widget Action Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Defines a widget action to retrieve tournament data. This action is configured to appear under the 'Data' tab in the admin interface. ```python @widget_action( widget_action_type=WidgetActionType.Action, tab="Data", title="Get tournament data", description="Get tournament data", wi ``` -------------------------------- ### Get Current Authenticated User Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Retrieves the current authenticated user object from the asynchronous context. This allows access to user details within the current task. ```python @property def user(self) -> Any | None: """Current authenticated user object for this async context.""" return self._user_context.get() ``` -------------------------------- ### Registering Models in FastAdmin Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Demonstrates how to register models with FastAdmin, including defining list display, links, filters, search fields, and form field overrides. It also shows how to define custom widget actions and methods like authentication and password changes. ```python from fastadmin import ( PonyORMInlineModelAdmin, PonyORMModelAdmin, WidgetActionArgumentProps, WidgetActionChartProps, WidgetActionFilter, WidgetActionInputSchema, WidgetActionParentArgumentProps, WidgetActionProps, WidgetActionResponseSchema, WidgetActionType, WidgetType, action, display, ) from fastadmin import fastapi_app as admin_app from fastadmin import ( register, widget_action, ) @register(User) class UserModelAdmin(PonyORMModelAdmin): menu_section = "Users" list_display = ("id", "username", "is_superuser") list_display_links = ("id", "username") list_filter = ("id", "username", "is_superuser") search_fields = ("username",) formfield_overrides = { # noqa: RUF012 "username": (WidgetType.SlugInput, {"required": True}), "password": (WidgetType.PasswordInput, {"passwordModalForm": True}), "avatar_url": ( WidgetType.UploadImage, { "required": False, # Disable crop image for upload field # "disableCropImage": True, }, ), "attachment_url": ( WidgetType.UploadFile, { "required": True, }, ), } widget_actions = ( "sales_chart", "sales_area_chart", "sales_column_chart", "sales_bar_chart", "sales_pie_chart", "sales_action", ) @db_session def authenticate(self, username: str, password: str) -> uuid.UUID | int | None: obj = next((f for f in User.select(username=username, password=password, is_superuser=True)), None) # fmt: skip if not obj: return None return obj.id @db_session def change_password(self, id: uuid.UUID | int, password: str) -> None: obj = next((f for f in self.model_cls.select(id=id)), None) if not obj: return # direct saving password is only for tests - use hash obj.password = password commit() def upload_file( self, field_name: str, file_name: str, file_content: bytes, obj: db.Entity | None = None, ) -> str: """This method is used to upload files. :params field_name: a name of field. :params file_name: a name of file. :params file_content: a content of file. :params obj: an orm/db model object. None on the add page, the existing instance on the change page. :return: A file url. """ # save file to media directory or to s3/filestorage here # return a full url to the file return f"https://fastadmin.io/media/{file_name}" ``` -------------------------------- ### Registering a Sales by Month Column Chart Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Sets up a column chart to show sales figures broken down by month. It includes a filter for the year selection. ```python @widget_action( widget_action_type=WidgetActionType.ChartColumn, widget_action_props=WidgetActionChartProps( x_field="x", y_field="y", series_field="series", series_color={ "2025": "#fa8c16", "2026": "#f5222d", }, ), widget_action_filters=[ WidgetActionFilter( field_name="year", widget_type=WidgetType.Select, widget_props={ "options": [ {"label": "2025", "value": "2025"}, {"label": "2026", "value": "2026"}, ], }, ), ], tab="Analytics", title="Sales by month", description="Column chart of sales", width=12, ) async def sales_column_chart(self, payload: WidgetActionInputSchema) -> WidgetActionResponseSchema: return WidgetActionResponseSchema( data=[ {"x": "Jan", "y": 320, "series": "2025"}, {"x": "Feb", "y": 410, "series": "2025"}, {"x": "Jan", "y": 380, "series": "2026"}, {"x": "Feb", "y": 460, "series": "2026"}, ], ) ``` -------------------------------- ### Define Non-Editable Fields in FastAPI Admin Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Use `readonly_fields` to specify fields that should display their data as-is and be non-editable. Example: `readonly_fields = ("created_at",)`. ```python readonly_fields: Sequence[str] = () ``` -------------------------------- ### Get Model Fields with Widget Types Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Abstract method to retrieve a list of model fields along with their associated widget types. Optionally include many-to-many fields. ```python def get_model_fields_with_widget_types( self, with_m2m: bool | None = None, ) -> list[ModelFieldWidgetSchema]: """This method is used to get model fields with widget types. :params with_m2m: a flag to include m2m fields. :return: A list of ModelFieldWidgetSchema. """ raise NotImplementedError ``` -------------------------------- ### Create Superuser with PonyORM Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Create a superuser account using PonyORM. This function ensures the admin user exists in the database. ```python @db_session def create_superuser(): User( username="admin", password="admin", is_superuser=True, attachment_url="/media/attachment.txt", ) ``` -------------------------------- ### Format and Lint with Biome Source: https://github.com/vsdudakov/fastadmin/blob/main/frontend/README.md Applies formatting and linting checks using Biome, with automatic fixes. ```bash yarn biome-check ``` -------------------------------- ### ORM Get Many-to-Many Field IDs Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Asynchronous method to retrieve the IDs of objects related through a many-to-many field for a given object. Requires the object instance and the field name. ```python async def orm_get_m2m_ids(self, obj: Any, field: str) -> list[int | UUID]: """This method is used to get m2m ids. :params obj: an object. :params field: a m2m field name. :return: A list of ids. """ raise NotImplementedError ``` -------------------------------- ### Registering a Sales Column Chart Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Sets up a column chart widget for displaying sales by month. It includes a filter for the year and defines specific colors for different years. ```python async def sales_column_chart(self, payload: WidgetActionInputSchema) -> WidgetActionResponseSchema: return WidgetActionResponseSchema( data=[ {"x": "Jan", "y": 320, "series": "2025"}, {"x": "Feb", "y": 410, "series": "2025"}, {"x": "Jan", "y": 380, "series": "2026"}, {"x": "Feb", "y": 460, "series": "2026"}, ], ) ``` -------------------------------- ### Get Model Primary Key Name Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Abstract method to retrieve the primary key name for a given ORM model class. This must be implemented by subclasses to specify how to identify the primary key. ```python @staticmethod def get_model_pk_name(orm_model_cls: Any) -> str: """This method is used to get model pk name. :return: A str. """ raise NotImplementedError ``` -------------------------------- ### Create Superuser Function Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Asynchronously creates a default superuser with username 'admin' and password 'admin'. This is typically used during application startup. ```python async def create_superuser(): await User.create( username="admin", password="admin", is_superuser=True, ) ``` -------------------------------- ### FastAPI Integration with FastAdmin Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/templates/readme.md Shows how to mount the FastAdmin application into a FastAPI application, ensuring that registered admin models are accessible. ```python from fastapi import FastAPI from fastadmin import fastapi_app as admin_app import myapp.admin # import to register User admin app = FastAPI() app.mount("/admin", admin_app) ``` -------------------------------- ### FastAPI Application Lifespan and Admin Mount Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Configure the FastAPI application lifespan to initialize the database and create a superuser. Mount the admin application at the '/admin' path and add CORS middleware for cross-origin requests. ```python @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: init_db() create_superuser() yield app = FastAPI(lifespan=lifespan) app.mount("/admin", admin_app) app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3030", "http://localhost:8090"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) ``` -------------------------------- ### Project Structure Overview Source: https://github.com/vsdudakov/fastadmin/blob/main/frontend/README.md Provides a hierarchical view of the source code directories and key files within the FastAdmin frontend project. ```tree src/ ├── main.tsx # Entry point, providers, root render ├── index.css # Global styles & design tokens ├── vite-env.d.ts # Type declarations (e.g. Window) ├── test-setup.ts # Vitest setup (e.g. ResizeObserver mock) │ ├── constants/ │ └── routes.ts # Route paths & helpers │ ├── containers/ # Page-level components (routes) │ ├── app/ # App shell, ConfigProvider, Routes │ ├── sign-in/ │ ├── index/ # Dashboard │ ├── list/ # List view with filters, actions │ ├── add/ # Add form │ └── change/ # Edit form │ ├── components/ │ ├── crud-container/ # Layout: header, sidebar, content card │ ├── sign-in-container/ │ ├── form-container/ # Dynamic forms from config │ ├── table-or-cards/ # List as table or cards (mobile) │ ├── filter-column/ │ ├── dashboard-widget/ # Charts & dashboard blocks │ ├── async-select/ # FK / autocomplete │ ├── async-transfer/ # M2M picker │ ├── upload-input/ # File/image upload │ ├── password-input/ # Password with change modal │ ├── slug-input/ │ ├── phone-number-input/ │ ├── json-textarea/ │ ├── texteditor-field/ # Rich text (Quill) │ └── export-btn/ │ ├── providers/ │ ├── ConfigurationProvider/ # App config from API │ └── SignInUserProvider/ # Auth state │ ├── fetchers/ │ └── fetchers.ts # API client (axios) │ ├── hooks/ │ ├── useTableQuery.ts # List pagination, filters, sort │ ├── useTableColumns.tsx │ └── useIsMobile.ts │ ├── helpers/ │ ├── configuration.ts │ ├── forms.ts # Error handling, form helpers │ ├── title.ts │ ├── transform.tsx # Server ↔ client data transform │ └── widgets.ts # Widget registry │ └── interfaces/ ├── configuration.ts # API/config types └── user.ts ``` -------------------------------- ### Use Input Widget for ForeignKey/ManyToManyField in FastAPI Admin Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Set `raw_id_fields` to a list of fields for which you want an Input widget instead of a select-box for ForeignKey or ManyToManyField. Example: `raw_id_fields = ("user",)`. ```python raw_id_fields: Sequence[str] = () ``` -------------------------------- ### Run Tests with Coverage Source: https://github.com/vsdudakov/fastadmin/blob/main/frontend/README.md Executes tests and generates a code coverage report. ```bash yarn coverage ``` -------------------------------- ### Sales Data Action Form Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Defines an action widget to get sales data, featuring various input fields like AsyncSelect, Select, and DatePicker, with conditional logic based on parent arguments. ```python @widget_action( widget_action_type=WidgetActionType.Action, widget_action_props=WidgetActionProps( arguments=[ # Example of using AsyncSelect widget with parentModel WidgetActionArgumentProps( name="user_id", widget_type=WidgetType.AsyncSelect, widget_props={ "required": True, "parentModel": "User", "idField": "id", "labelFields": ["__str__", "id"], }, ), # Example of using Select widget with dynamically loaded options WidgetActionArgumentProps( name="username", widget_type=WidgetType.Select, widget_props={ "required": True, # dynamically load options from the database in pre_generate_models_schema method "options": [], }, ), # Example of using parent argument with filtered children arguments WidgetActionArgumentProps( name="type", widget_type=WidgetType.Select, widget_props={ "required": True, "options": [ {"label": "Sales", "value": "sales"}, {"label": "Revenue", "value": "revenue"}, ], }, ), WidgetActionArgumentProps( name="sales_date", widget_type=WidgetType.DatePicker, widget_props={ "required": True, }, parent_argument=WidgetActionParentArgumentProps( name="type", value="sales", ), ), WidgetActionArgumentProps( name="revenue_date", widget_type=WidgetType.DatePicker, widget_props={ "required": True, }, parent_argument=WidgetActionParentArgumentProps( name="type", value="revenue", ), ), ], ), tab="Data", title="Get sales data", description="Get sales data", width=12, ) async def sales_action(self, payload: WidgetActionInputSchema) -> WidgetActionResponseSchema: return WidgetActionResponseSchema( data=[ {"id": 1, "name": "Sales"}, {"id": 2, "name": "Sales"}, {"id": 3, "name": "Sales"}, ], ) ``` -------------------------------- ### Add Help Text for Search Box in FastAPI Admin Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Use `search_help_text` to provide descriptive text for the search box, displayed below it. Example: `search_help_text = "Search by mobile number or email"`. ```python search_help_text: str = "" ``` -------------------------------- ### Register Sales Bar Chart Widget Action Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Sets up a bar chart widget action for sales data, including configuration for x and y fields, series, and series colors. It also includes placeholder for filters. ```python @widget_action( widget_action_type=WidgetActionType.ChartBar, widget_action_props=WidgetActionChartProps( x_field="x", y_field="y", series_field="series", series_color={ "Q1": "#2f54eb", "Q2": "#eb2f96", }, ), widget_action_filters=[ ``` -------------------------------- ### Specify List Ordering in FastAPI Admin Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Set `ordering` to define the order of objects in admin views. Format is similar to a model's `ordering` parameter. Example: `ordering = ("-created_at",)`. ```python ordering: Sequence[str] = () ``` -------------------------------- ### Enable Search Functionality in FastAPI Admin Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Set `search_fields` to a list of field names to enable a search box on the admin list page. Example: `search_fields = ("mobile_number", "email")`. ```python search_fields: Sequence[str] = () ``` -------------------------------- ### Configure List Filters in FastAPI Admin Source: https://github.com/vsdudakov/fastadmin/blob/main/docs/index.html Use `list_filter` to activate filters in the table columns of the list page. Example: `list_filter = ("is_superuser", "is_active", "created_at")`. ```python list_filter: Sequence[str] = () ```