Skip to main content

A library for creating forms in aiogram3

Project description

aiogram3-form

A library for creating forms in aiogram3

pip install aiogram3-form

What is a form?

Form is a set of fields that you want your user to fill in. Forms are defined as classses derived from aiogram3_form.Form and contain fields with annotated types and aiogram3_form.FormField values. You should not inherit your form class from your another form class (so no deep inheritance).

When you start your form with .start() method, your bot will ask a user input values one by one until the end. Filling in the last field of a form means "submitting" it.

Forms use default aiogram FSM.

Minimal example

import asyncio

from aiogram import Bot, Dispatcher, F
from aiogram.fsm.context import FSMContext

from aiogram3_form import Form, FormField

bot = Bot(token="YOUR_TOKEN")
dispatcher = Dispatcher()


class NameForm(Form):
    first_name: str = FormField(enter_message_text="Enter your first name please")
    second_name: str = FormField(
        enter_message_text="Enter your second name please",
        filter=(F.text.len() > 10) & F.text,
    )
    age: int = FormField(enter_message_text="Enter age as integer")


@NameForm.submit(
    router=dispatcher,  # also might use aiogram.Router here
    clear_state=False,  # if you want to keep fsm state,
    # defaults to True (sets state to None before calling your submit function)
)
async def name_form_submit_handler(form: NameForm):
    # handle form submitted data
    # also supports aiogram standart DI (e. g. middleware, filter data, etc.)
    # you can do anything you want in here

    # .answer() method of a form object is not the only way to reply
    # use can also use bot.send_message with form.chat_id for example
    await form.answer(f"{form.first_name} {form.second_name} of age {form.age}")


@dispatcher.message(F.text == "/form")
async def form_handler(_, state: FSMContext):
    await NameForm.start(bot, state)  # start your form


asyncio.run(dispatcher.start_polling(bot))

Keyboards

You can use any type of keyboard in your form, but only reply keyboards are actually useful (because forms only accept messages as input, so no callback queries).

from aiogram.utils.keyboard import ReplyKeyboardBuilder
from aiogram.types import KeyboardButton

FRUITS = ("Orange", "Apple", "Banana")

fruits_markup = (
    ReplyKeyboardBuilder().add(*(KeyboardButton(text=f) for f in FRUITS)).as_markup()
)


class FruitForm(Form):
    fruit: str = FormField(
        enter_message_text="Pick your favorite fruit",
        filter=F.text.in_(FRUITS) & F.text,
        reply_markup=fruits_markup,
    )

Form filters

Default filters are built in for types: str (checks for message text and returns it), int (tries to convert message text to int), float, datetime.date, datetime.datetime, aiogram.types.PhotoSize, aiogram.types.Document, aiogram.types.Message

Supported form filter kinds: sync function, async function, aiogram magic filter.

If your filter is a function (sync or async), it should take aiogram.types.Message as the first argument and return False, if it does not pass. If a filter passed, it should return the value you want in your form data.

Magic filters return None on failure, so it's a special case that is handled differently.

If your filter fails and error_message_text is provided in FormField call, an error message will be sent with the provided text.

def sync_fruit_form_filter(message: types.Message) -> str | bool:
    if message.text not in FRUITS:
        return False

    return message.text


async def async_fruit_form_filter(
    message: types.Message,
): ...  # some async fruit filtering


class FruitForm(Form):
    fruit: str = FormField(
        enter_message_text="Pick your favorite fruit",
        filter=sync_fruit_form_filter,  # you can pass an async filter here as well
        reply_markup=fruits_markup,
        error_message_text="Thats an invalid fruit",
    )

Enter callback

Enter callbacks enable you to write your own enter functions for form fields. In case you provide your own enter callback, the enter_message_text parameter of aiogram3.FormField will be ignored.

from aiogram import types


async def enter_fruit_callback(chat_id: int, user_id: int, data: dict[str, Any]) -> types.Message:
    # do whatever you want in here
    print(f"user {user_id} has just entered the fruit callback in chat {chat_id}!")

    return await bot.send_message(
        chat_id, "Hey, pick your favorite fruit please", reply_markup=fruits_markup
    )


class FruitForm(Form):
    fruit: str = FormField(
        enter_callback=enter_fruit_callback,
        filter=sync_fruit_form_filter,
        error_message_text="Thats an invalid fruit",
    )

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aiogram3_form-2.0.5.tar.gz (6.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aiogram3_form-2.0.5-py3-none-any.whl (7.9 kB view details)

Uploaded Python 3

File details

Details for the file aiogram3_form-2.0.5.tar.gz.

File metadata

  • Download URL: aiogram3_form-2.0.5.tar.gz
  • Upload date:
  • Size: 6.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.13.2 Darwin/23.2.0

File hashes

Hashes for aiogram3_form-2.0.5.tar.gz
Algorithm Hash digest
SHA256 4d2d9f8814edbac6cb69e912eef53d7ac913aaaf3d00f0dd0c5004534caef778
MD5 fb92cfef61cd201b582c2b470a3699f1
BLAKE2b-256 1de83ac5ef9c3367cf1bc2d3941d97b29d621bb6836dbba01ee48e3e78d944f7

See more details on using hashes here.

File details

Details for the file aiogram3_form-2.0.5-py3-none-any.whl.

File metadata

  • Download URL: aiogram3_form-2.0.5-py3-none-any.whl
  • Upload date:
  • Size: 7.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.13.2 Darwin/23.2.0

File hashes

Hashes for aiogram3_form-2.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 9d40ebdb395a60c51b18ca88523ce9b6ee94ec54c8e8fe2c60e3832d18c5fe1a
MD5 457f8139b7324e753e5f612862577733
BLAKE2b-256 f51d64029a8184cfd9247a7f1c77244091d660d154272ccb662cac1a31bbccb8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page