Skip to content

Plugin

Plugins in fastack are just python modules/packages which are imported in app build. All plugins can be added to the app via the PLUGINS configuration in the app settings. Then we'll look for the setup() function and then pass the app instance to the setup() function. So you can add anything to the app, like adding startup and shutdown events to initialize your plugin. See below...

Create a plugin

Let's create a plugin for logging purposes

Note

Plugins can be placed anywhere, but we recommend in the app/plugins folder

app/plugins/logger.py
import logging
import sys

from fastack import Fastack
from fastack.globals import LocalProxy, state

log: logging.Logger = LocalProxy(lambda: state.log)


def setup(app: Fastack):
    def on_startup():
        log = logging.getLogger("fastack_logger")
        handler = logging.StreamHandler(sys.stdout)
        formatter = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
        )
        handler.setFormatter(formatter)
        log.addHandler(handler)
        if app.debug:
            log.setLevel(logging.DEBUG)

        app.state.log = log
        log.info("Fastack logger initialized")

    def on_shutdown():
        log.info("Fastack logger cleanup")
        del app.state.log

    app.add_event_handler("startup", on_startup)
    app.add_event_handler("shutdown", on_shutdown)

Lines:

  • 7 - Get the Logger object. See line 19.
  • 16, 17 - Set the logging level to DEBUG if the app is in debug mode.
  • 19 - Set the Logger object to app.state, so we can make it globally accessible.

Adding a plugin

Put the plugin into the PLUGINS configuration according to the settings of the app being used.

PLUGINS = [
    ...,
    "app.plugins.logger",
]

Test it

examples/helloworld/app/controllers/helloworld/__init__.py
from app.plugins.globalvar import say_hello
from app.plugins.logger import log
from fastapi import Response
from pydantic import conint

from fastack.controller import ReadOnlyController
from fastack.decorators import route
from fastack.globals import request
from fastack.models import DetailModel, PaginatedModel

from .models import HelloWorldModel


class HelloWorldController(ReadOnlyController):
    name = "helloworld"
    url_prefix = "/world"

    def say_hello(self):
        if say_hello:
            log.debug("Hello there!")

    @route(response_model=PaginatedModel[HelloWorldModel])
    def list(self, page: conint(gt=0) = 1, page_size: conint(gt=0) = 10) -> Response:
        self.say_hello()
        data = [
            {"id": i, "title": request.url_for("helloworld:list")} for i in range(5)
        ]
        return self.get_paginated_response(data, page, page_size)

    @route(response_model=DetailModel[HelloWorldModel])
    def retrieve(self, id: int) -> Response:
        self.say_hello()
        return self.json(
            "Detail",
            {"id": id, "title": request.url_for("helloworld:single_update", id=id)},
        )

    @route(
        "/{id}/update",
        action=True,
        methods=["PUT"],
        response_model=DetailModel[HelloWorldModel],
    )
    def single_update(self, id: int) -> Response:
        self.say_hello()
        return self.json("Update", {"id": id, "title": "hello mars"})

Lines:

  • 2 - We import global logger object
  • 20 - We print Hello there! if global variable say_hello is True.

The code above is taken from the example project


Last update: January 17, 2022 13:26:42