Skip to content

Plugin Management

This guide explains how to manage plugins in Fast Pluggy.

Understanding Plugins

Plugins in Fast Pluggy are Python packages that extend the functionality of your FastAPI application. Each plugin can:

  • Add new routes and endpoints
  • Provide new UI components
  • Extend the admin interface
  • Add new database models
  • Integrate with external services

Installing Plugins

Using the Admin Interface

The easiest way to install plugins is through the admin interface:

  1. Navigate to /admin/plugins in your application
  2. Click on "Install New Plugin"
  3. Enter the plugin package name or URL
  4. Click "Install"

Using the API

You can also install plugins programmatically:

from fastapi import FastAPI
from fastpluggy import FastPluggy
from fastpluggy.core.plugin.installer import PluginInstaller

app = FastAPI()
pluggy = FastPluggy(app)

# Get the plugin installer
plugin_installer = PluginInstaller(plugin_manager=pluggy.get_manager())

# Install a plugin from a Git repository
result = plugin_installer.install_plugin("https://github.com/example/fastpluggy-auth.git")
print(f"Installation result: {result}")

# Install requirements for an existing plugin
plugin_installer.install_module_requirements(module_name="my-plugin", fast_pluggy=pluggy)

Managing Plugins

Checking Plugin Status

You can check if a plugin is loaded:

# Get the module manager
module_manager = pluggy.module_manager

# Check if a module is loaded
is_loaded = module_manager.is_module_loaded("my-plugin")
print(f"Plugin loaded: {is_loaded}")

Executing Plugin Hooks

You can execute hooks for all plugins:

# Execute a hook for all modules
module_manager.execute_all_module_hook(hook_name="on_load_complete")

Refreshing Plugin States

To refresh the plugin states from the database:

module_manager.refresh_plugins_states()

Creating Plugins

Basic Plugin Structure

A Fast Pluggy plugin has the following structure:

my-plugin/
├── __init__.py
├── plugin.py
├── routes.py
├── models.py
└── templates/
    └── index.html

Plugin Class

Every plugin must define a class that inherits from FastPluggyBaseModule:

# plugin.py
from fastapi import APIRouter
from pathlib import Path
from typing import Optional, Dict, Any

from fastpluggy.core.module_base import FastPluggyBaseModule

def get_router():
    """
    Wrap router in a function to avoid circular imports & plugin dependencies issue on loading.
    """
    from .routes import router
    return router

class MyPlugin(FastPluggyBaseModule):
    # Identity and version
    module_name: str = "my-plugin"
    module_version: str = "0.1.0"
    depends_on: Dict[str, str] = {"fastpluggy": ">=0.1.0"}

    # Menu metadata
    module_menu_name: str = "My Plugin"
    module_menu_icon: str = "fas fa-puzzle-piece"
    module_menu_type: str = "main"  # or "admin"

    # Router configuration
    module_mount_url: Optional[str] = "/my-plugin"
    module_router: Any = get_router()

    # Lifecycle hooks
    def on_load_complete(self, fast_pluggy):
        """Called when all plugins are loaded."""
        # Initialize your plugin here
        pass

    def after_setup_templates(self, fast_pluggy):
        """Called when templates are set up."""
        # Add custom template globals or filters
        pass

Plugin Routes

Define routes in your plugin:

# routes.py
from fastapi import APIRouter

router = APIRouter(prefix="/my-plugin")

@router.get("/")
def index():
    return {"message": "Hello from my plugin!"}

Plugin Models

Define database models for your plugin:

# models.py
from sqlalchemy import Column, Integer, String
from fastpluggy.core.models_tools.sqlalchemy import Base

class MyModel(Base):
    __tablename__ = "my_plugin_items"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    description = Column(String)

Plugin Dependencies

Plugins can depend on other plugins by specifying them in the depends_on dictionary:

class MyPlugin(FastPluggyBaseModule):
    # ...
    depends_on: Dict[str, str] = {
        "fastpluggy": ">=0.1.0",
        "auth-plugin": ">=0.2.0"
    }
    # ...

Plugin Configuration

Plugins can define and access configuration through the module_settings attribute:

from fastpluggy.core.config import BaseDatabaseSettings

# Define your plugin's settings model
class MyPluginSettings(BaseDatabaseSettings):
    api_key: str = ""
    debug: bool = False
    max_items: int = 100

class MyPlugin(FastPluggyBaseModule):
    # ...
    module_settings: Optional[MyPluginSettings] = None

    def on_load_complete(self, fast_pluggy):
        # Initialize settings if not already set
        if not self.module_settings:
            self.module_settings = MyPluginSettings()

        # Access settings
        api_key = self.module_settings.api_key
        debug = self.module_settings.debug

        # Use configuration values
        if debug:
            print(f"Debug mode enabled, API key: {api_key}")

Settings can also be loaded from the database or environment variables by extending the configuration system.

Topbar Actions

Plugins can add icon buttons to the admin topbar (the sticky header) by registering TopbarAction entries in the GlobalRegistry. Buttons appear on the right-hand side of the topbar, sorted by position (lower = leftmost).

Action modes

Three mutually exclusive modes, evaluated in priority order:

Mode Field Behaviour
Modal modal_widgets Widget list rendered server-side into a Bootstrap modal. The button uses data-bs-toggle="modal" — no JS required.
JS js_onclick Arbitrary JS expression in onclick="...".
Link url Plain <a> navigation link.

Pass a list of widget instances to modal_widgets. The framework pre-renders them into a dedicated <div class="modal" id="fp-modal-{id}"> in the page HTML at request time. Clicking the button opens the modal via Tabler/Bootstrap's data-bs-toggle — no JavaScript needed.

Each widget is deep-copied and processed per request, so shared instances registered at startup are safe across concurrent requests.

from fastpluggy.core.global_registry import GlobalRegistry
from fastpluggy.core.topbar import TopbarAction
from fastpluggy.core.widgets.categories.input.button_list import ButtonListWidget
from fastpluggy.core.widgets.categories.input.button import AutoLinkWidget

class MyPlugin(FastPluggyBaseModule):
    ...
    def on_load_complete(self, fast_pluggy, plugin):
        GlobalRegistry.extend_globals('topbar_actions', items=[
            TopbarAction(
                id='my-plugin-topbar',
                icon='ti ti-star',
                tooltip='My Plugin',
                position=20,
                modal_widgets=[
                    {
                        'widget': ButtonListWidget,
                        'kwargs': {
                            'title': "My Plugin",
                            'buttons': [
                                AutoLinkWidget(route_name="my_index", label="Home"),
                                AutoLinkWidget(route_name="my_settings", label="Settings"),
                            ],
                        },
                    },
                ],
                module_name='my_plugin',
            )
        ])

The rendered button:

<button class="fp-icon-btn" id="my-plugin-topbar" type="button"
        title="My Plugin"
        data-bs-toggle="modal" data-bs-target="#fp-modal-my-plugin-topbar">
    <i class="ti ti-star"></i>
</button>

Tip

debug_tools uses this pattern: its bug-icon button opens a modal with a ButtonListWidget of quick-access debug links (env vars, routes, registry, etc.).


JS action

TopbarAction(
    id='my-action',
    icon='ti ti-player-play',
    tooltip='Run task',
    position=30,
    js_onclick='myRunTask()',
    module_name='my_plugin',
)

The JS function must be available on the page. Deliver it via extra_js_files:

class MyPlugin(FastPluggyBaseModule):
    extra_js_files: list = ['/plugin-pkg/my_plugin/static/js/actions.js']

TopbarAction(
    id='open-docs',
    icon='ti ti-book',
    tooltip='Documentation',
    position=80,
    url='/docs',
)

TopbarAction field reference

Field Type Default Description
id str Unique HTML id for the <button> or <a>.
icon str CSS icon classes, e.g. "ti ti-bug" or "fas fa-wrench".
tooltip str "" title attribute shown on hover.
position int 50 Sort order — lower values appear further left.
modal_widgets list [] Widget instances pre-rendered into a server-side modal. Takes priority over js_onclick and url.
js_onclick str \| None None JS expression in onclick="...". Takes priority over url.
url url \| None None Navigation URL (renders as <a>).
extra_classes str "" Additional CSS classes on the button element.
module_name str "" Your plugin's module_name — links the action to the plugin admin overview.

Next Steps

After setting up plugins, check out the API Reference for more details on the Fast Pluggy API.