RealWorld: aiohttp, Tortoise ORM

?v=1

На Real World отсутствует пример для aiohttp, и я решил его сделать. Опытным разработчикам, похоже, некогда этим заниматься, а начинающим в aiohttp непонятно как делать правильно. Я начал его делать с помощью Tortoise ORM. Пока начал делать аутентификацию.

Хочется сделать этот проект правильно, поэтому под катом очень много вопросов опытным aiohttp разработчкам.


Установка проекта

Репозиторий

Склонируйте репозиторий:


git clone git@github.com: nomhoi/aiohttp-realworld-example-app.git

При разработке я использовал Python 3.8. Установите зависимости:


pip install -r requirements.txt

Инициализируем базу данных:


python init_db.py

Запускаем сервер:


python -m conduit

В репозитории присутствует Postman коллекция RealWorld.postman_collection.json. Импортируйте ее в Postman и можете попробовать получившийся API.


PostgreSQL

По умолчанию используется база данных SQLite.

Для использования PostrgeSQL нужно изменить переменную DB_URL в /conduit/settings.py.


DB_URL = «postgres://postgres: postgres@0.0.0.0:5432/postgres»

Запустить сервис базы данных:


docker-compose up -d

После этого инициализировать базу данных:


python init_db.py


Файловая структура проекта

Структура проекта выполнена в соответствии с современным подходом принятым в Django: все приложения находятся на том же уровне что и папка проекта. Это позволяет повторно использовать созданные приложения без их изменения в других проектах.

Аутентификация, профили и статьи будут выполнены в виде отдельных приложений, как и в примере RealWorld для Django.

Папка проекта — conduit.


Реализованное API

Спецификация API здесь

POST /api/users — регистрация пользователя

POST /api/users/login — аутентификация пользователя

GET /api/user — получение данных текущего пользователя

Обработчики этих запросов находятся в /authentication/views.py.


CORS

Использована библиотека aiohttp_cors.

# Configure default CORS settings.
cors = aiohttp_cors.setup(app, defaults={
    "*": aiohttp_cors.ResourceOptions(
        allow_credentials=True,
        expose_headers="*",
        allow_headers="*",
    )
})

# Configure CORS on all routes.
for route in list(app.router.routes()):
    cors.add(route)

Как видим, все включено и разрешено для всех ориджинов, и выполнена общая настройка для всех роутов.

Здесь можете подсказать, как лучше настроить.


JWT

Используется aiohttp_jwt:

    app = web.Application(
        middlewares=[
            JWTMiddleware(
                settings.SECRET_KEY,
                whitelist=[
                    r'/api/users',
                ]
            )
        ]
    )

JWT работает, только в заголовке Authorizstion вместо Token ставится слово Bearer. В примере для Django — Token. Будет ли работать нормально с фронтэндами пока не проверял.


Модель User

Используется Tortoise ORM

class TimestampedMixin:
    created_at = fields.DatetimeField(auto_now_add=True)
    updated_at = fields.DatetimeField(auto_now=True)

class AbstractBaseModel(Model):
    id = fields.IntField(pk=True)

    class Meta:
        abstract = True

class User(TimestampedMixin, AbstractBaseModel):
    username = fields.CharField(db_index=True, max_length=255, unique=True)
    email = fields.CharField(db_index=True, max_length=255, unique=True)
    password = fields.CharField(max_length=128)

    class Meta:
        table = "user"

    def __str__(self):
        return self.username

Пока не нашел, как сделать сортировку как в Django примере:

ordering = ['-created_at', '-updated_at']

Думаю, что лучше всего вычисление токена из вьюхи переместить в модель User. Оформить его в виде свойства.

Хранение паролей планирую выполнить как в Django: хэш + соль с алгоритмом PBKDF2. Пока не выполнено.


Миграции

У Tortoise ORM отсутствуют автоматические миграции. По условиям задачи такое требование отсутствует, поэтому реализовывать не буду.


Сериализаторы

Пока сделал без сериализаторов. Нашел такой проект, но там старая версия Tortoise ORM.

Существуют и другие реализации сериализаторов. Наверное, с ними разработка ведется идиоматичнее и быстрее. Надо попробовать. ORM прицепили, теперь надо и сериализаторы добавить. А может и рендеров еще добавить?


Тесты

Пока не добавил. По условиям задачи тесты можно сделать, но они не обязательны.


Заключение

Нужно еще добавить поддержку профилей, статей и еще много чего. Приглашаются к проекту все желающие прославить свое имя на века и тысячелетия. Приветствуются подсказки и замечания опытных разработчиков.

© Habrahabr.ru