Slack webhooks API served by FastAPI

Overview

Slackers

Slack webhooks API served by FastAPI

What is Slackers

Slackers is a FastAPI implementation to handle Slack interactions and events. It serves endpoints to receive slash commands, app actions, interactive components. It also listens for events sent to the Slack Events API Slack Events.

Installation

You can install Slackers with pip $ pip install slackers

Configuration

SLACK_SIGNING_SECRET

You must configure the slack signing secret. This will be used to verify the incoming requests signature.
$ export SLACK_SIGNING_SECRET=your_slack_signing_secret

Example usage

Slackers will listen for activity from the Events API on /events, for interactive components on /actions and for slash commands on /commands. When an interaction is received, it will emit an event. You can listen for these events as shown in the following examples.

On receiving a request, Slackers will emit an event which you can handle yourself. Slackers will also respond to Slack with an (empty) http 200 response telling Slack all is well received.

Starting the server

As said, Slackers uses the excellent FastAPI to serve it's endpoints. Since you're here, I'm assuming you know what FastAPI is, but if you don't, you can learn all about how that works with this tutorial.

Slackers offers you a router which you can include in your own FastAPI.

from fastapi import FastAPI
from slackers.server import router

app = FastAPI()
app.include_router(router)

# Optionally you can use a prefix
app.include_router(router, prefix='/slack')

Events

Once your server is running, the events endpoint is setup at /events, or if you use the prefix as shown above, on /slack/events.

Accepting the challenge

When setting up Slack to send events, it will first send a challenge to verify your endpoint. Slackers detects when a challenge is sent. You can simply start our api and Slackers will meet the challenge automatically.

Responding to events

On receiving an event, Slackers will emit a python event, which you can act upon as shown below.

import logging
from slackers.hooks import events

log = logging.getLogger(__name__)

@events.on("app_mention")
def handle_mention(payload):
    log.info("App was mentioned.")
    log.debug(payload)

Actions

Once your server is running, the actions endpoint is setup at /actions, or if you use the prefix as shown above, on /slack/actions.

Responding to actions

On receiving an action, Slackers will emit a python event, which you can listen for as shown below. You can listen for the action type, or more specifically for the action id or callback id linked to the action.

import logging
from slackers.hooks import actions

log = logging.getLogger(__name__)

# Listening for the action type.
@actions.on("block_actions")
def handle_action(payload):
    log.info("Action started.")
    log.debug(payload)

# Listen for an action by it's action_id
@actions.on("block_actions:your_action_id")
def handle_action_by_id(payload):
    log.info("Action started.")
    log.debug(payload)

# Listen for an action by it's callback_id
@actions.on("block_actions:your_callback_id")
def handle_action_by_callback_id(payload):
    log.info(f"Action started.")
    log.debug(payload)

Interactive messages

Interactive message actions do not have an action_id. They do have a name and a type. To act upon interactive messages, you can listen for the action type, interactive_message as wel as the combination of the interactive_message and name, type or both.

import logging
from slackers.hooks import actions

log = logging.getLogger(__name__)

# Listening for the action type.
@actions.on("interactive_message")
def handle_action(payload):
    log.info("Action started.")
    log.debug(payload)

# Listen for an action by it's name
@actions.on("interactive_message:action_name")
def handle_action_by_id(payload):
    log.info("Action started.")
    log.debug(payload)

# Listen for an action by it's type
@actions.on("interactive_message:action_type")
def handle_action_by_callback_id(payload):
    log.info(f"Action started.")
    log.debug(payload)

# Listen for an action by it's name and type
@actions.on("interactive_message:action_name:action_type")
def handle_action_by_callback_id(payload):
    log.info(f"Action started.")
    log.debug(payload)

Custom responses

Slackers tries to be fast to respond to Slack. The events you are listening for with the likes of @actions.on(...) are scheduled as an async task in a fire and forget fashion. After scheduling these events, Slackers will by default return an empty 200 response which might happen before the events are handled.

In some cases you might want to act on the payload and return a custom response to Slack. For this, you can use the slackers responder decorator to define your custom handler function. This function is then used as a callback instead of returning the default response. You must ensure your custom handler returns a starlette.responses.Response or one of it's subclasses. You must furthermore ensure that there is only one responder responding to your Slack request.

Please note that the events are also emitted, so you could have both @actions.on("block_action:xyz") and @responder("block_action:xyz"). Just keep in mind that the event emissions are async and are not awaited. In other words, Slackers doesn't ensure that the response (whether your custom response or the default) is returned before or after the events are emitted.

from starlette.responses import JSONResponse
from slackers.hooks import responder

@responder("block_actions:your_callback_id")
def custom_handler(payload):
    # handle your payload
    ...
    return JSONResponse(content={"custom": "Custom Response"})

Slash commands

Once your server is running, the commands endpoint is setup at /commands, or if you use the prefix as shown above, on /slack/commands. Slackers will emit an event with the name of the command, so if your command is /engage, you can listen for the event engage (without the slash)

Responding to slash commands

On receiving a command, Slackers will emit a python event, which you can listen for as shown below.

import logging
from slackers.hooks import commands

log = logging.getLogger(__name__)


@commands.on("engage")  # responds to "/engage"  
def handle_command(payload):
    log.info("Command received")
    log.debug(payload)

Async

Since events are emitted using pyee's Async event emitter, it is possible to define your event handlers as async functions. Just keep in mind that errors are in this case emitted on the 'error' event.

import logging
from slackers.hooks import commands

log = logging.getLogger(__name__)

@commands.on('error')
def log_error(exc):
    log.error(str(exc))


@commands.on("engage")  # responds to "/engage"  
async def handle_command(payload):
    ...
Comments
  • Add support for view event payloads

    Add support for view event payloads

    Hi @uhavin!

    First of all, this is a great utility library, so keep up the good work! Just to let you know, I have been using it for my Slack bot to keep my Python code neat (decorators ftw!).

    Back to this PR. So far, view payloads would be directed to the /actions endpoint as well since Slack mentioned here that view payloads would be directed to the same Request URL as interactive components and app actions. However, since the SlackAction Pydantic model that you have defined did not specify any view blocks, it was simply discarded.

    This PR fixes this issue by adding support for a view dictionary in the SlackAction Pydantic model. This also allows specifying a particular view payload's callback_id to listen to.

    Cheers!

    opened by jamestiotio 12
  • 422 Unprocessable Entity for app_home_opened

    422 Unprocessable Entity for app_home_opened

    I am unable to process app_home_opened events, getting 422 errors. I am able to process 'message.im' events fine. Is there an issue with the incoming payloads on these two being different?

    https://api.slack.com/events/message.im { "token": "one-long-verification-token", "team_id": "T061EG9R6", "api_app_id": "A0PNCHHK2", "event": { "type": "message", "channel": "D024BE91L", "user": "U2147483697", "text": "Hello hello can you hear me?", "ts": "1355517523.000005", "event_ts": "1355517523.000005", "channel_type": "im" }, "type": "event_callback", "authed_teams": [ "T061EG9R6" ], "event_id": "Ev0PV52K21", "event_time": 1355517523 }

    https://api.slack.com/events/app_home_opened { "type": "app_home_opened", "user": "U061F7AUR", "channel": "D0LAN2Q65", "event_ts": "1515449522000016", "tab": "home", "view": { "id": "VPASKP233", "team_id": "T21312902", "type": "home", "blocks": [ ... ], "private_metadata": "", "callback_id": "", "state":{ ... }, "hash":"1231232323.12321312", "clear_on_close": false, "notify_on_close": false, "root_view_id": "VPASKP233", "app_id": "A21SDS90", "external_id": "", "app_installed_team_id": "T21312902", "bot_id": "BSDKSAO2" } }

    opened by GH-maggio 5
  • [BUG] Interactive messages don't have 'action_id'

    [BUG] Interactive messages don't have 'action_id'

    Hello there!

    I've found an issue. When I have an action type being interactive_message, the data I receive doesn't contain an action_id, only name, type and selected_options, therefore I receive this error:

    INFO:     34.207.162.7:0 - "POST /slack/actions HTTP/1.1" 500 Internal Server Error
    ERROR:    Exception in ASGI application
    Traceback (most recent call last):
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/uvicorn/protocols/http/h11_impl.py", line 389, in run_asgi
        result = await app(self.scope, self.receive, self.send)
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
        return await self.app(scope, receive, send)
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/fastapi/applications.py", line 149, in __call__
        await super().__call__(scope, receive, send)
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/starlette/applications.py", line 102, in __call__
        await self.middleware_stack(scope, receive, send)
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/starlette/middleware/errors.py", line 181, in __call__
        raise exc from None
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in __call__
        await self.app(scope, receive, _send)
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
        raise exc from None
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in __call__
        await self.app(scope, receive, sender)
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/starlette/routing.py", line 550, in __call__
        await route.handle(scope, receive, send)
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/starlette/routing.py", line 227, in handle
        await self.app(scope, receive, send)
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/starlette/routing.py", line 41, in app
        response = await func(request)
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/fastapi/routing.py", line 196, in app
        raw_response = await run_endpoint_function(
      File "/home/marcelo/anaconda3/envs/coinprice/lib/python3.8/site-packages/fastapi/routing.py", line 148, in run_endpoint_function
        return await dependant.call(**values)
      File "/home/marcelo/Development/fastapi/slackers/src/slackers/server.py", line 47, in post_actions
        triggered_events = [
      File "/home/marcelo/Development/fastapi/slackers/src/slackers/server.py", line 48, in <listcomp>
        f"{action.type}:{triggered_action['action_id']}"
    

    Can someone help me?

    Changing the conditionals on the server.actions solves the problem:

    @router.post(
        "/actions",
        status_code=HTTP_200_OK,
        dependencies=[Depends(verify_signature), Depends(check_timeout)],
    )
    async def post_actions(request: Request) -> Response:
        form = await request.form()
        form_data = json.loads(form["payload"])
        # have the convenience of pydantic validation
        action = SlackAction(**form_data)
        _events = [action.type]
        if action.callback_id:
            _events.append(f"{action.type}:{action.callback_id}")
        elif action.actions: 
            triggered_events = [
                f"{action.type}:{triggered_action['action_id']}"
                for triggered_action in action.actions
            ]
            _events.extend(triggered_events)
    

    @uhavin are you still maintaining this package?

    opened by Kludex 4
  • Add text attribute to command model

    Add text attribute to command model

    Currently the text passed along with a Slash command is stripped out by Pydantic. Adding this allows you to use /command some random message.

    I tested this locally and it doesn't matter if no text is passed along in the command since Slack always passes this key in the payload.

    opened by kylecrawshaw 4
  • Input validation for view_submission actions

    Input validation for view_submission actions

    Hi @uhavin, I would like to bring up this issue regarding input validation for view_submission actions.

    Modals provide the ability for developers to add input blocks to which users can respond to. If a developer were to attempt to validate the inputs sent through a view_submission action, they can follow the instructions detailed here.

    Basically, the developer could respond with this payload:

    {
      "response_action": "errors",
      "errors": {
        "<block_id>": "Some text here"
      }
    }
    

    However, using this library, currently it is not possible for us to respond with a custom object as such (if it is possible, do enlighten me on how to execute it). From what I know, this part of the code will be sent first before any custom code is executed:

    https://github.com/uhavin/slackers/blob/ede0cdb821edbd9b053a68b634cf78e0cd7ed35d/src/slackers/server.py#L61

    Due to its empty body, Slack's server will assume that everything went fine and the modal will just be closed without any further follow-up. Thus, any object that is going to be returned after that will be ignored.

    Is it possible to somehow modify the aforementioned part of the code to enable developers to provide input validation? Perhaps some kind of option to write a custom object that overrides the default one? Another idea would be to include a try clause. Thank you!

    opened by jamestiotio 4
  • custom response

    custom response

    Thanks for this great library! I was able to process actions but I'm having issues with custom responses. I have my code that looks as follows:

    @actions.on("block_actions:approve_workflow")
    def handle_workflow_unpause_action(payload):
        log.info("Action started.")
        log.debug(payload)
        print("action: ", payload)
    
    
    @responder("block_actions:approve_workflow")
    def respond_to_workflow_unpause_action(payload):
        log.info("Response.")
        log.debug(payload)
        print("response: ", payload)
        user = payload["user"]["username"]
        return JSONResponse(
            {
                "replace_original": "true",
                "text": f"Workflow approved by @{user}",
            }
        )
    

    The issue is I'm expecting the original block_action to be replaced by the message Workflow approved by {user}. But this doesn't seem to be happening. Is there something I'm missing? Thanks for your help and providing this library!

    opened by vallard 2
  • 500 Error when Trying to Verify Slack App

    500 Error when Trying to Verify Slack App

    We're trying to incorporate this library into an FAQ API we've built on top of FastAPI.

    When we try to enable the endpoint via Slack, the response is an HTTP error.

    Here is the output from uvicorn:

    INFO:     44.195.79.65:52938 - "POST /slack/events HTTP/1.1" 500 Internal Server Error
    ERROR:    Exception in ASGI application
    Traceback (most recent call last):
      File "/usr/local/lib/python3.8/dist-packages/uvicorn/protocols/http/h11_impl.py", line 396, in run_asgi
        result = await app(self.scope, self.receive, self.send)
      File "/usr/local/lib/python3.8/dist-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
        return await self.app(scope, receive, send)
      File "/usr/local/lib/python3.8/dist-packages/fastapi/applications.py", line 199, in __call__
        await super().__call__(scope, receive, send)
      File "/usr/local/lib/python3.8/dist-packages/starlette/applications.py", line 112, in __call__
        await self.middleware_stack(scope, receive, send)
      File "/usr/local/lib/python3.8/dist-packages/starlette/middleware/errors.py", line 181, in __call__
        raise exc from None
      File "/usr/local/lib/python3.8/dist-packages/starlette/middleware/errors.py", line 159, in __call__
        await self.app(scope, receive, _send)
      File "/usr/local/lib/python3.8/dist-packages/starlette/middleware/cors.py", line 78, in __call__
        await self.app(scope, receive, send)
      File "/usr/local/lib/python3.8/dist-packages/starlette/exceptions.py", line 82, in __call__
        raise exc from None
      File "/usr/local/lib/python3.8/dist-packages/starlette/exceptions.py", line 71, in __call__
        await self.app(scope, receive, sender)
      File "/usr/local/lib/python3.8/dist-packages/starlette/routing.py", line 580, in __call__
        await route.handle(scope, receive, send)
      File "/usr/local/lib/python3.8/dist-packages/starlette/routing.py", line 241, in handle
        await self.app(scope, receive, send)
      File "/usr/local/lib/python3.8/dist-packages/starlette/routing.py", line 52, in app
        response = await func(request)
      File "/usr/local/lib/python3.8/dist-packages/fastapi/routing.py", line 191, in app
        solved_result = await solve_dependencies(
      File "/usr/local/lib/python3.8/dist-packages/fastapi/dependencies/utils.py", line 548, in solve_dependencies
        solved = await call(**sub_values)
      File "/usr/local/lib/python3.8/dist-packages/slackers/verification.py", line 29, in verify_signature
        os.environ.get("SLACK_SIGNING_SECRET").encode(), to_verify, sha256
    AttributeError: 'NoneType' object has no attribute 'encode'
    

    The routes appear on the FastAPI /docs page (screenshot attached) FastAPI_routes

    For now, we've just included the very basics of the code implementation, which we understand should automatically handle the Slack Events requests. We've also confirmed that the env variables are set on the OS (Ubuntu).

    
    from fastapi import FastAPI, HTTPException
    import uvicorn
    
    # SlackBot Imports
    import os
    from slack_sdk import WebClient
    from slack_sdk.errors import SlackApiError
    from slackers.server import router
    from slackers.hooks import actions
    from slackers.hooks import responder
    from slackers.hooks import events
    from dotenv import load_dotenv
    
    # Slack variables
    load_dotenv()
    signing_secret = os.environ.get("SLACK_SIGNING_SECRET")
    slack_token = os.environ.get("SLACK_BOT_TOKEN")
    
    app = FastAPI()
    app.include_router(router, prefix='/slack')
    

    Any help is greatly appreciated and please let me know if you need more info.

    opened by hops-on-pop 2
  • Add empty py.typed file to show module supports PEP 561

    Add empty py.typed file to show module supports PEP 561

    This file tells mypy (and possibly other type checking tools) that the slackers library has type annotations which can be used for type checking.

    It's necessary if you want stricter type checks between the code that implements a Slack bot and the slacker library.

    opened by Tenzer 2
  • Receiving actions by callback_id

    Receiving actions by callback_id

    I try to receive actions by callback_id but it only reaches /actions witch does nothing but to return a 200 Ok response :

    @commands.on("newreq3")
    def handle_command(payload):
        print("Command received")
        print(payload)
        slack_web_client.api_call(
            api_method="dialog.open",
            json= { 
            "trigger_id": payload["trigger_id"],
            "dialog" : {
                "title": "Nouvelle permission",
                "submit_label": "Envoyer",
                "callback_id": "newreqc",
    [...]
    
    @actions.on("block_actions:newreqc")
    def handle_action(payload):
        print("Action started.")
        print(payload)
    
    @actions.on("block_actions")
    def handle_action2(payload):
        slack_web_client.chat_postMessage(
                channel='C01EWV6DL9K',
                text="Asking for permission ?")
        print(payload)
    
    

    So the dialog box well open when launching command, the submit button sends a callback on /actions only where I think it should send a callback on /actions/newreqc. Here with your stack I can't see what's inside the callback since I didn't succeed in catching it.

    INFO:     3.90.1.212:0 - "POST /commands HTTP/1.0" 200 OK
    Command received
    {'token': '---------', 'command': '/newreq3', 'response_url': 'https://hooks.slack.com/commands/T01F673DS04/1524134228434/ib7GScKFh45MqXa9juInAZnW', 'trigger_id': '1517403300102.1516241468004.4231bd72bc1b564c08851f55f5947949', 'user_id': 'U01ETA7UDJA', 'user_name': 'gs', 'team_id': 'T01F673DS04', 'channel_id': 'C01EWV6DL9K', 'text': ''}
    INFO:     54.198.138.148:0 - "POST /actions HTTP/1.0" 200 OK
    
    opened by DrGkill 2
  • [Question] How to test events or commands?

    [Question] How to test events or commands?

    Hello, could you please help me to create some examples how to test handlers?

    eg. This is a handler using a save_text function, I know I cam simply test save_text and other parts.

    
    from fastapi import FastAPI
    from slackers.hooks import commands
    from slackers.models import SlackCommand
    from slackers.server import router
    
    app = FastAPI(debug=True)
    app.include_router(router)
    app.include_router(router, prefix="/slack")
    
    
    async def save_text(text: str):
        with open("command_log.txt", "a+") as outf:
            print(text, file=outf)
    
    
    @commands.on("cmd")
    async def handle_command(payload):
        cmd = SlackCommand(**payload).text
        # .. more complex parsing of cmd in between
        await save_text(cmd)
    
    

    This is my test:

    from fastapi.testclient import TestClient
    
    
    def test_shout_command( client: TestClient):
        command_data = {
            "token": "1234erfghjuiop",
            "command": "/cmd",
            "response_url": "https://hooks.slack.com/commands/ABCDEFG/1289665550278/6RQ7UIUXhMzAFXwApOPiMB1o",
            "trigger_id": "1296602173907.524169929122.0fa6d05ec3b37886607b56011efcbc9d",
            "user_id": "UFE4ZTC8J",
            "user_name": "1user1",
            "team_id": "TFE4ZTB3L",
            "channel_id": "D0184EACFNK",
            "text": "to <@UJ03ECZLG|1user1_1> <@UJ03E1ESU|1user1_2> for less",
        }
        head = {
            "x-slack-signature": "mySecret",
            "x-slack-request-timestamp": "1531420618"
        }
        resp = client.post("/slack/commands", data=command_data, headers=head)
        print(resp)
        assert resp.ok
    

    But response I receive is 403.

    Could you please recommend how can I test handle_command with pytest?

    opened by 1oglop1 2
  • Message builder .blocks formatter

    Message builder .blocks formatter

    The format of the message that the MessageBuilder.dict returns, is good for the Slack API. The python slackclient however, implements chat_postMessage accepting a blocks parameter. It would be convenient to have a helper method on the message object, so we can use it like so

    slack_web_client.chat_postMessage(channel="ABC", blocks=message.slack_blocks())
    
    opened by uhavin 2
  • Bump certifi from 2021.10.8 to 2022.12.7

    Bump certifi from 2021.10.8 to 2022.12.7

    Bumps certifi from 2021.10.8 to 2022.12.7.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
Owner
Niels van Huijstee
Niels van Huijstee
:rocket: CLI tool for FastAPI. Generating new FastAPI projects & boilerplates made easy.

Project generator and manager for FastAPI. Source Code: View it on Github Features ?? Creates customizable project boilerplate. Creates customizable a

Yagiz Degirmenci 1k Jan 2, 2023
Пример использования GraphQL Ariadne с FastAPI и сравнение его с GraphQL Graphene FastAPI

FastAPI Ariadne Example Пример использования GraphQL Ariadne с FastAPI и сравнение его с GraphQL Graphene FastAPI - GitHub ###Запуск на локальном окру

ZeBrains Team 9 Nov 10, 2022
Sample-fastapi - A sample app using Fastapi that you can deploy on App Platform

Getting Started We provide a sample app using Fastapi that you can deploy on App

Erhan BÜTE 2 Jan 17, 2022
Flask-vs-FastAPI - Understanding Flask vs FastAPI Web Framework. A comparison of two different RestAPI frameworks.

Flask-vs-FastAPI Understanding Flask vs FastAPI Web Framework. A comparison of two different RestAPI frameworks. IntroductionIn Flask is a popular mic

Mithlesh Navlakhe 1 Jan 1, 2022
FastAPI Server Session is a dependency-based extension for FastAPI that adds support for server-sided session management

FastAPI Server-sided Session FastAPI Server Session is a dependency-based extension for FastAPI that adds support for server-sided session management.

DevGuyAhnaf 5 Dec 23, 2022
fastapi-admin2 is an upgraded fastapi-admin, that supports ORM dialects, true Dependency Injection and extendability

FastAPI2 Admin Introduction fastapi-admin2 is an upgraded fastapi-admin, that supports ORM dialects, true Dependency Injection and extendability. Now

Glib 14 Dec 5, 2022
Code Specialist 27 Oct 16, 2022
Fastapi-ml-template - Fastapi ml template with python

FastAPI ML Template Run Web API Local $ sh run.sh # poetry run uvicorn app.mai

Yuki Okuda 29 Nov 20, 2022
FastAPI-Amis-Admin is a high-performance, efficient and easily extensible FastAPI admin framework. Inspired by django-admin, and has as many powerful functions as django-admin.

简体中文 | English 项目介绍 FastAPI-Amis-Admin fastapi-amis-admin是一个拥有高性能,高效率,易拓展的fastapi管理后台框架. 启发自Django-Admin,并且拥有不逊色于Django-Admin的强大功能. 源码 · 在线演示 · 文档 · 文

AmisAdmin 318 Dec 31, 2022
A Python framework to build Slack apps in a flash with the latest platform features.

Bolt for Python A Python framework to build Slack apps in a flash with the latest platform features. Read the getting started guide and look at our co

SlackAPI 684 Jan 9, 2023
api versioning for fastapi web applications

fastapi-versioning api versioning for fastapi web applications Installation pip install fastapi-versioning Examples from fastapi import FastAPI from f

Dean Way 472 Jan 2, 2023
api versioning for fastapi web applications

fastapi-versioning api versioning for fastapi web applications Installation pip install fastapi-versioning Examples from fastapi import FastAPI from f

Dean Way 127 Feb 17, 2021
High-performance Async REST API, in Python. FastAPI + GINO + Arq + Uvicorn (w/ Redis and PostgreSQL).

fastapi-gino-arq-uvicorn High-performance Async REST API, in Python. FastAPI + GINO + Arq + Uvicorn (powered by Redis & PostgreSQL). Contents Get Star

Leo Sussan 351 Jan 4, 2023
Boilerplate code for quick docker implementation of REST API with JWT Authentication using FastAPI, PostgreSQL and PgAdmin ⭐

FRDP Boilerplate code for quick docker implementation of REST API with JWT Authentication using FastAPI, PostgreSQL and PgAdmin ⛏ . Getting Started Fe

BnademOverflow 53 Dec 29, 2022
API Simples com python utilizando a biblioteca FastApi

api-fastapi-python API Simples com python utilizando a biblioteca FastApi Para rodar esse script são necessárias duas bibliotecas: Fastapi: Comando de

Leonardo Grava 0 Apr 29, 2022
REST API with FastAPI and JSON file.

FastAPI RESTAPI with a JSON py 3.10 First, to install all dependencies, in ./src/: python -m pip install -r requirements.txt Second, into the ./src/

Luis Quiñones Requelme 1 Dec 15, 2021
REST API with FastAPI and PostgreSQL

REST API with FastAPI and PostgreSQL To have the same data in db: create table CLIENT_DATA (id SERIAL PRIMARY KEY, fullname VARCHAR(50) NOT NULL,email

Luis Quiñones Requelme 1 Nov 11, 2021
Complete Fundamental to Expert Codes of FastAPI for creating API's

FastAPI FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3 based on standard Python type hints. The key featu

Pranav Anand 1 Nov 28, 2021
Basic fastapi blockchain - An api based blockchain with full functionality

Basic fastapi blockchain - An api based blockchain with full functionality

null 1 Nov 27, 2021