Skip to content

Новое приложение

После разбора структуры проекта давайте добавим новое app которое будет отвечать за отправку email сообщений и получения кэшированной истории сообщений! А добавить его очень легко, просто выполните команду:

python manage.py g a emailapp
tower g a emailapp

Note

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

У вас будет следующая структура проекта:

├── emailapp/
│   ├── __init__.py
│   ├── admin.py
│   ├── config.py
│   ├── models.py
│   ├── routers.py
│   ├── serializers.py
│   └── views.py
├── example/
│   ├── __init__.py
│   ├── asgi.py
│   ├── routers.py
│   └── settings.py
└── manage.py

Подключение приложения

Таких приложений может быть много и важно все приложения которые используются вносить в INSTALLED_APPS

INSTALLED_APPS = [
    'fasttower.apps.taerich',
    'fasttower.auth',
    ...,
    'emailapp',
]
settings.py
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "l6q4CY6UhJXppm8TjiyhUF2nhEGaX1aPao3RnkyRavY"

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ["*"]

INSTALLED_APPS = [
    'fasttower.apps.taerich',
    'fasttower.auth',
    'emailapp',
]

MIDDLEWARE = [
    ["fastapi.middleware.trustedhost.TrustedHostMiddleware", {"allowed_hosts": ALLOWED_HOSTS}],
    ["fastapi.middleware.gzip.GZipMiddleware", {"minimum_size": 1000, "compresslevel": 5}],
]
if DEBUG:
    MIDDLEWARE += ["debug_toolbar.middleware.DebugToolbarMiddleware"],

USER_MODEL = 'fasttower.auth.models.BaseUser'

ASGI = "example.asgi:app"

LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_TZ = True

# Database
DATABASES = {
    "connections": {
        "default": {
            "engine": "tortoise.backends.sqlite",
            "credentials": {
                "file_path": str(BASE_DIR / "db.sqlite3"),
            }
        },
    },
}

CACHE = {
    "default": {
        "BACKEND": "fasttower.cache.InMemoryBackend",
    }
}

#https://github.com/fastapi-admin/fastapi-admin
ADMIN_PANEL_REDIS = 'redis://localhost:6379/0'

Структура приложения

config.py

Отвечает за инициализацию моделей, cli команд

config.py

from fasttower.apps.config import AppBaseConfig


class AppConfig(AppBaseConfig):
    app = 'emailapp'

Если вам требуется инициализировать что-либо при запуске проекта, внесите это в функцию read

from fasttower.apps.config import AppBaseConfig


class AppConfig(AppBaseConfig):
    app = 'emailapp'

    def read(self):
        ...

models.py

ORM

В настоящее время из коробки поддерживаться только Tortoise-orm

models.py

from fasttower.db import models

В настоящее время models.Model реализует только primary key

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

    class Meta:
        abstract = True

Пример модели

from email.message import EmailMessage

from fasttower.conf import settings
from fasttower.db import models
from fasttower.email import send_mail


class EmailMessageModel(models.Model):
    subject = models.CharField(max_length=100)
    content = models.TextField()
    to = models.CharField(max_length=255)
    create_at = models.DatetimeField(auto_now_add=True, null=True, default=None)

    async def send(self):
        message = EmailMessage()
        message["From"] = settings.SMTP['default']['from_']
        message["To"] = self.to
        message["Subject"] = self.subject
        message.set_content(self.content)
        await send_mail(message=message)

Документация Tortoise https://tortoise.github.io/

admin.py

Admin panel

В настоящее время совместимо только с Tortoise-orm

Вы должны увидеть следующее содержимой, а так же просмотреть документацию можно тут https://fastapi-admin-docs.long2ice.io/

admin.py

```python from fastapi_admin.resources import Model, Dropdown from fasttower import admin

from emailapp import models

@admin.site.app.register class EmailappTabMenu(Dropdown): label = "emailapps" icon = "fas fa-bars" resources = [] title = "Emailapps" ```

Создаем модель

После того как вы разобрались со структурой приложений, давай те сделаем первую модель которая будет хранить subject,content,to,create_at. Для этого создайте класс унаследованный от models.Model

class EmailMessageModel(models.Model):

И добавьте новые поля

subject = models.CharField(max_length=100)
content = models.TextField()
to = models.CharField(max_length=255)
create_at = models.DatetimeField(auto_now_add=True, null=True, default=None)

Полный код

from email.message import EmailMessage

from fasttower.conf import settings
from fasttower.db import models
from fasttower.email import send_mail


class EmailMessageModel(models.Model):
    subject = models.CharField(max_length=100)
    content = models.TextField()
    to = models.CharField(max_length=255)
    create_at = models.DatetimeField(auto_now_add=True, null=True, default=None)

async def send(self):
    message = EmailMessage()
    message["From"] = settings.SMTP['default']['from_']
    message["To"] = self.to
    message["Subject"] = self.subject
    message.set_content(self.content)
    await send_mail(message=message)

Конечные точки

в файле views.py, задайте две конечные точки:

Полный код

from emailapp.models import EmailMessageModel
from pydantic import EmailStr

from fasttower.cache import cache
from fasttower.routers import APIRouter

router = APIRouter()


@router.get("/send")
async def send_message(subject: str, content: str, to: EmailStr):
    message = EmailMessageModel(subject=subject, content=content, to=to)
    await message.save()
    await message.send()


@router.get("/history")
@cache(expire=1)
async def message_history():
    return await EmailMessageModel.all()

Использую следующий декоратор, вы задаете время кэширования в минутах

@cache(expire=1)

Убедитесь в уставленном lifespan для кэша cache_lifespan

    app = FastTower(title="FastTower API Documentation", lifespan=lifespans([cache_lifespan]))

Note

Подключите router к главному роутеру в example/routers.py

emailapp/routers.py

from fasttower.routers import APIRouter

from emailapp.views import router as email_router

router = APIRouter(prefix="/emailapp", tags=["emailapp"])
router.include_router(email_router)

example/routers.py

from fasttower.routers import APIRouter

from emailapp.views import router as email_router

router = APIRouter(prefix="/emailapp", tags=["emailapp"])
router.include_router(email_router)

Подключаем SMTP

В файле settings.py установите следующую настройку

SMTP = {
    'default': {
        'backend': 'fasttower.email.backends.AIOEmailBackend',
        'hostname': 'smtp.example.org',
        'port': 465,
        'username': 'example',
        'password': 'example',
        'use_tls': True,
        'start_tls': False,
        'from_': 'example@example.org'
    }
}

Миграции

Мы подошли к концу, давайте создадим миграции и запустим приложение

Миграции

python manage.py db init
tower db init

Note

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

После успешного создания миграций, в корне проекта вы обнаружите соответствующую папку и sql для обновления бд

Запуск

python manage.py run
tower run

Note

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

На этом все, вы можете перейти в свагер и отправить письмо, а так же получить всю историю писем!