13g10n
Напишите мне
На главную

Вышла стабильная версия aiogram-forms

Наконец вышла стабильная версия aiogram-forms! Ну, честно говоря, версия 1.0.0 вышла ещё 30 декабря, но заметка выходит только сейчас, т.к. в январе я занимался обновлениями для блога и другими проектами.

Прежде всего, релиз нацелен на поддержку 3-й версии aiogram, которая, кстати, оказалась достаточно приятной в плане API лично для меня. Также вся внутрянка была переписана с нуля, покрыта тестами и аннотациями типов на 100%, чтобы максимально избежать возможных проблем.

Давайте рассмотрим использование aiogram-forms на примере бота для регистрации пользователей. Прежде всего, там нужно описать форму: почта с подсказкой, номер телефона с возможностью пошарить контакт в один клик и пароль:

from aiogram_forms.forms import Form, fields, FormsManager

class RegisterForm(Form):
    email = fields.EmailField('Почта', help_text='Мы отправим код подтверждения.')
    phone = fields.PhoneNumberField('Телефон', share_contact=True)
    password = fields.TextField('Пароль')

Помимо generic полей и их валидаторов, мы можем использовать параметр validators для определения своих правил для поля и даже переопределить сообщения об ошибках через error_messages:

from aiogram_forms.errors import ValidationError

def validate_password_format(value: str):
    special_characters = "!@#$%^&*()-+?_=,<>/"
    if not any(character in special_characters for character in value):
        raise ValidationError('Пароль должен содержать как минимум один специальный символ!', code='weak_password')

class RegisterForm(Form):
    ...
    password = fields.TextField(
        'Пароль',
        min_length=8,
        validators=[validate_password_format],
        error_messages={
            'min_length': 'Пароль должен содержать не менее 8 символов!'
        }
    )

Далее, регистрируем форму с уникальным идентификатором, который после можно будет использовать для взаимодействия с формой:

from aiogram_forms import dispatcher

@dispatcher.register('register')
class RegisterForm(Form):
    ...

Чтобы обработать сабмит нашей формы после процессинга всех полей, можно добавить метод callback в нашу форму. К примеру, чтобы сказать спасибо после валидации последнего поля формы:

class RegisterForm(Form):
    ...

    @classmethod
    async def callback(cls, message: types.Message, **data) -> None:
        await message.answer(text='Спасибо! Мы свяжемся с вами для уточнения деталей.')

На данном этапе, у нас есть всё, чтобы позволить нашим пользователям заполнять форму. Для того чтобы вызвать обработчик формы, мы используем менеджер FormsManager, доступный автоматически через инжектор зависимостей aiogram:

from aiogram_forms.forms import FormsManager

@router.message(Command(commands=['start']))
async def command_start(message: Message, forms: FormsManager) -> None:
    await forms.show('register')

Таким же образом мы имеем возможность использовать метод get_data менеджера чтобы получить поля формы в формате словаря:

class RegisterForm(Form):
    email = fields.EmailField('Почта', help_text='Мы отправим код подтверждения.')
    ...

    @classmethod
    async def callback(cls, message: types.Message, forms: FormsManager, **data) -> None:
        data = await forms.get_data(RegisterForm)
        await my_service.send_confirmation(data['email'])
        await message.answer(text=f'Спасибо! На ваш адрес отправлено письмо с кодом подтверждения.')

Наскоро собранная документация доступна здесь (будет обновляться). Вопросы и проблемы можно оставлять в issues - уведомления просматриваю каждый день. Если проект оказался интересным или полезным, поставьте, пожалуйста, ему звезду на GitHub ⭐️

Python
Telegram
aiogram
aiogram-forms