<p align="center">
<a href="https://pysashapy.github.io/fasttower/"><img src="docs/img/logo.png" alt="FastTower" width="256"></a>
</p>
<p align="center">
<em>FastTower — это молодой фреймворк основанный на FastAPI для быстрого создания серверных приложений с Django-like структурой.</em>
</p>
<p align="center">
<a href="https://pypi.org/project/fasttower" target="_blank">
<img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/fasttower">
</a>
<a href="https://pypi.org/project/fasttower" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fasttower.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
## Features
- Легкая настройка
- Высокая производительность
- Простота в использовании
- Админ панель
## Быстрый старт
В настоящее время официально поддерживаться только tortoise orm и админ панель для нее, но вы можете легко добавить свою
поддержку бд модернизируя
FastTower app в asgi.py файле
[Полный пример](https://github.com/pysashapy/fasttower/tree/main/examples/start)
### Установка
```console
pip install fasttower[tortoise]
```
Так же для управления миграциями требуется aerich, а именно его модернизированный форк
```console
pip install git+https://github.com/pysashapy/taerich.git@0.0.1
```
### Создание проекта
Для начала требуется сгенерировать основное приложение
```console
tower g p example
```
После выполнения команды, вы можете обнаружить Django-like структуру проекта и сразу же запустить сервер
```console
python manage.py run
```
<details markdown="1">
<summary>Или другим сервером...</summary>
```console
uvicorn example.asgi:app
```
</details>
### Обзор
Главная роль manage.py файла установить env **FASTTOWER_SETTINGS_MODULE** указывающею путь до вашего settings.py
файла(**example.settings**). Вы можете
установить ее сами и после этого использовать команду **tower**. Далее будет использоваться команда **tower**, но вы
всегда можете использовать **python manage.py**
<details markdown="1">
<summary>Запуск с установленной env...</summary>
```console
tower run
```
</details>
### Структура проекта
#### asgi.py
FastTower - это полностью совместимый FastAPI class.
```python
"""
ASGI config for example project.
It exposes the ASGI callable as a module-level variable named ``application``.
"""
import os
from fasttower.utils import setup
os.environ.setdefault("FASTTOWER_SETTINGS_MODULE", "example.settings")
setup()
from fasttower.server import FastTower
from example.routers import router
app = FastTower(title="FastTower API Documentation")
app.include_router(router)
```
<details markdown="1">
<summary>Если не нужен tortoise...</summary>
Уберите lifespan
```Python
lifespan=lifespans([tortoise_lifespan])
```
</details>
#### settings.py
Вправду очень похоже на Django?
Основные поля: INSTALLED_APPS, MIDDLEWARE, USER_MODEL(Только tortoise!)
```python
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "niJEjVCDfqHI_Fke_oUDVgcqkfWfW8ZEoUT_OQxVKco"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ["*"]
INSTALLED_APPS = [
'fasttower.apps.taerich',
'fasttower.auth',
]
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"),
}
},
},
}
# https://github.com/fastapi-admin/fastapi-admin
ADMIN_PANEL_REDIS = 'redis://localhost:6379/0'
```
##### INSTALLED_APPS
После создания нового приложения обязательно добавьте его в **INSTALLED_APPS**! Иначе у FastTower не будет доступа к
моделям и командам
приложения
```python
INSTALLED_APPS = [
'fasttower.apps.taerich',
'fasttower.auth',
...
'appexample',
]
```
##### MIDDLEWARE
Поддерживаются все starlette совместимые middleware!
Структура MIDDLEWARE
```python
MIDDLEWARE = [
["fastapi.middleware.trustedhost:TrustedHostMiddleware", {"allowed_hosts": ALLOWED_HOSTS}],
["fastapi.middleware.gzip:GZipMiddleware", {"minimum_size": 1000, "compresslevel": 5}],
...
["path:class", {...kwargs}],
]
```
#### routers.py
Является отправной точкой для всех будущих APPs
```python
from fasttower.routers import APIRouter
router = APIRouter(prefix="/api/v1")
router.include_router(APP_ROUTER, prefix='/app')
```
### Создание нового приложения
Выполните команду которая создаст приложение
```console
tower g a appexample
```
После ее выполнения обязательно добавьте приложение в **settings.py -> INSTALLED_APPS**
```python
INSTALLED_APPS = [
'fasttower.apps.taerich',
'fasttower.auth',
...
'appexample',
]
```
Каждое приложение содержит **config.py, models.py, admin.py, serializers.py, routers.py и views.py**
#### Models
Основано на [tortoise](https://tortoise.github.io/), так что вы можете просто импортировать ее и работать с ней!
```python
from fasttower.db import models
class FastTowerModel(models.Model):
say = models.CharField(max_length=100, default="Hello World!")
```
#### Admin
Тут содержится описание моделей для [админ панели](https://fastapi-admin-docs.long2ice.io/)
```python
from fastapi_admin.resources import Model, Dropdown
from fasttower import admin
from appexample import models
@admin.site.app.register
class AppexampleTabMenu(Dropdown):
label = "Appexamples"
icon = "fas fa-bars"
resources = []
title = "Appexamples"
```
#### Views
Тут все аналогично FastAPI, скоро появятся **mixins** как в Django для простых **CRUD** задач!
```python
from appexample.models import FastTowerModel
from fasttower.routers import APIRouter
router = APIRouter()
@router.get("/")
async def say():
return await FastTowerModel().create()
```
Не забудьте подключить в **appexample.routers**, а так же в **example.routers**
### Admin panel
Является экспериментальной функцией. В настоящее время для ее работы требуется
[**Redis**](https://github.com/redis/redis-py)
Проверьте в settings.py
```
ADMIN_PANEL_REDIS = 'redis://localhost:6379/0'
```
А так же включите его в asgi.py
```python
from fasttower.admin.site import app as admin_app, lifespan_admin
from fasttower.db import lifespan
app = FastTower(title="FastTower API Documentation", lifespan=lifespans([lifespan, lifespan_admin]))
app.mount('/admin', admin_app)
```
<details markdown="1">
<summary>Полный код...</summary>
```python
"""
ASGI config for example project.
It exposes the ASGI callable as a module-level variable named ``application``.
"""
import os
from fasttower.utils import setup, lifespans
os.environ.setdefault("FASTTOWER_SETTINGS_MODULE", "example.settings")
setup()
from fasttower.server import FastTower
from example.routers import router
from fasttower.admin.site import app as admin_app, lifespan_admin
from fasttower.db import lifespan
app = FastTower(title="FastTower API Documentation", lifespan=lifespans([lifespan, lifespan_admin]))
app.mount('/admin', admin_app)
app.include_router(router)
```
</details>
### Commands
Список текущих команд и их описания вы можете получить используя команду
```console
tower --help
```
```text
Usage: tower [OPTIONS] COMMAND [ARGS]...
╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --install-completion Install completion for the current shell. │
│ --show-completion Show completion for the current shell, to copy it or customize the installation. │
│ --help Show this message and exit. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ db Database commands │
│ g Generate project structures and app components for FastTower. │
│ run Запуск FastTower сервера │
│ shell Запускает интерактивную оболочку. │
│ superuser Create a superuser. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
#### Создание новых команд
Для этого создайте файл в папке **app**(appexample) commands.py
```python
import typer
example_commands = typer.Typer(name="appexample", help="Example commands")
@example_commands.command()
def hello_world():
print("Hello World!")
```
Вот и все её можно запустить!
```console
tower appexample hello-world
```
```console
Hello World!
```
Более детально про [Typer](https://typer.tiangolo.com/)
## Продолжение следует...
Raw data
{
"_id": null,
"home_page": "https://github.com/pysashapy/fasttower",
"name": "fasttower",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": "python, api, framework, web, rest, async, swagger, python3, asyncio, easy-web, starlette, fastapi, fasttower",
"author": "Alexander Ibragmov",
"author_email": "sasha.2000ibr@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/3b/85/9fcad6f255ea7fc30e4ca26e48868588308543f2132b4f380defcfed4d62/fasttower-0.1.6.tar.gz",
"platform": null,
"description": "<p align=\"center\">\n <a href=\"https://pysashapy.github.io/fasttower/\"><img src=\"docs/img/logo.png\" alt=\"FastTower\" width=\"256\"></a>\n</p>\n<p align=\"center\">\n <em>FastTower \u2014 \u044d\u0442\u043e \u043c\u043e\u043b\u043e\u0434\u043e\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 FastAPI \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441 Django-like \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439.</em>\n</p>\n<p align=\"center\">\n<a href=\"https://pypi.org/project/fasttower\" target=\"_blank\">\n <img alt=\"PyPI - Downloads\" src=\"https://img.shields.io/pypi/dm/fasttower\">\n</a>\n<a href=\"https://pypi.org/project/fasttower\" target=\"_blank\">\n <img src=\"https://img.shields.io/pypi/pyversions/fasttower.svg?color=%2334D058\" alt=\"Supported Python versions\">\n</a>\n</p>\n\n## Features\n\n- \u041b\u0435\u0433\u043a\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\n- \u0412\u044b\u0441\u043e\u043a\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\n- \u041f\u0440\u043e\u0441\u0442\u043e\u0442\u0430 \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438\n- \u0410\u0434\u043c\u0438\u043d \u043f\u0430\u043d\u0435\u043b\u044c\n\n## \u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442\n\n\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e tortoise orm \u0438 \u0430\u0434\u043c\u0438\u043d \u043f\u0430\u043d\u0435\u043b\u044c \u0434\u043b\u044f \u043d\u0435\u0435, \u043d\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0435\u0433\u043a\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u044e\n\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0431\u0434 \u043c\u043e\u0434\u0435\u0440\u043d\u0438\u0437\u0438\u0440\u0443\u044f\nFastTower app \u0432 asgi.py \u0444\u0430\u0439\u043b\u0435\n\n[\u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440](https://github.com/pysashapy/fasttower/tree/main/examples/start)\n\n### \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430\n\n```console\npip install fasttower[tortoise]\n```\n\n\u0422\u0430\u043a \u0436\u0435 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f\u043c\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f aerich, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0435\u0433\u043e \u043c\u043e\u0434\u0435\u0440\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0444\u043e\u0440\u043a\n\n```console\npip install git+https://github.com/pysashapy/taerich.git@0.0.1\n```\n\n### \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\n\n\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\n\n```console\ntower g p example\n```\n\n\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c Django-like \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\n\n```console\npython manage.py run\n```\n\n<details markdown=\"1\">\n<summary>\u0418\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c...</summary>\n```console\nuvicorn example.asgi:app \n```\n</details>\n\n### \u041e\u0431\u0437\u043e\u0440\n\n\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0440\u043e\u043b\u044c manage.py \u0444\u0430\u0439\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c env **FASTTOWER_SETTINGS_MODULE** \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u044e \u043f\u0443\u0442\u044c \u0434\u043e \u0432\u0430\u0448\u0435\u0433\u043e settings.py\n\u0444\u0430\u0439\u043b\u0430(**example.settings**). \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435\n\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0435\u0435 \u0441\u0430\u043c\u0438 \u0438 \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 **tower**. \u0414\u0430\u043b\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 **tower**, \u043d\u043e \u0432\u044b\n\u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c **python manage.py**\n<details markdown=\"1\">\n<summary>\u0417\u0430\u043f\u0443\u0441\u043a \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0439 env...</summary>\n```console\ntower run\n```\n</details>\n\n### \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\n\n#### asgi.py\n\nFastTower - \u044d\u0442\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 FastAPI class.\n\n```python\n\"\"\"\nASGI config for example project.\n\nIt exposes the ASGI callable as a module-level variable named ``application``.\n\"\"\"\n\nimport os\n\nfrom fasttower.utils import setup\n\nos.environ.setdefault(\"FASTTOWER_SETTINGS_MODULE\", \"example.settings\")\nsetup()\n\nfrom fasttower.server import FastTower\n\nfrom example.routers import router\n\napp = FastTower(title=\"FastTower API Documentation\")\n\napp.include_router(router)\n```\n\n<details markdown=\"1\">\n<summary>\u0415\u0441\u043b\u0438 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d tortoise...</summary>\n\u0423\u0431\u0435\u0440\u0438\u0442\u0435 lifespan\n```Python\nlifespan=lifespans([tortoise_lifespan])\n```\n</details>\n\n#### settings.py\n\n\u0412\u043f\u0440\u0430\u0432\u0434\u0443 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 Django?\n\n\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u043e\u043b\u044f: INSTALLED_APPS, MIDDLEWARE, USER_MODEL(\u0422\u043e\u043b\u044c\u043a\u043e tortoise!)\n\n```python\nfrom pathlib import Path\n\nBASE_DIR = Path(__file__).resolve().parent.parent\n\n# SECURITY WARNING: keep the secret key used in production secret!\nSECRET_KEY = \"niJEjVCDfqHI_Fke_oUDVgcqkfWfW8ZEoUT_OQxVKco\"\n\n# SECURITY WARNING: don't run with debug turned on in production!\nDEBUG = True\n\nALLOWED_HOSTS = [\"*\"]\n\nINSTALLED_APPS = [\n 'fasttower.apps.taerich',\n 'fasttower.auth',\n]\n\nMIDDLEWARE = [\n [\"fastapi.middleware.trustedhost:TrustedHostMiddleware\", {\"allowed_hosts\": ALLOWED_HOSTS}],\n [\"fastapi.middleware.gzip:GZipMiddleware\", {\"minimum_size\": 1000, \"compresslevel\": 5}],\n]\nif DEBUG:\n MIDDLEWARE += [\"debug_toolbar.middleware:DebugToolbarMiddleware\"],\n\nUSER_MODEL = 'fasttower.auth.models:BaseUser'\n\nASGI = \"example.asgi:app\"\n\nLANGUAGE_CODE = \"en-us\"\nTIME_ZONE = \"UTC\"\nUSE_TZ = True\n\n# Database\nDATABASES = {\n \"connections\": {\n \"default\": {\n \"engine\": \"tortoise.backends.sqlite\",\n \"credentials\": {\n \"file_path\": str(BASE_DIR / \"db.sqlite3\"),\n }\n },\n },\n}\n\n# https://github.com/fastapi-admin/fastapi-admin\nADMIN_PANEL_REDIS = 'redis://localhost:6379/0'\n```\n\n##### INSTALLED_APPS\n\n\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0435\u0433\u043e \u0432 **INSTALLED_APPS**! \u0418\u043d\u0430\u0447\u0435 \u0443 FastTower \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a\n\u043c\u043e\u0434\u0435\u043b\u044f\u043c \u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u043c\n\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\n\n```python\nINSTALLED_APPS = [\n 'fasttower.apps.taerich',\n 'fasttower.auth',\n ...\n 'appexample',\n]\n```\n\n##### MIDDLEWARE\n\n\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 starlette \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435 middleware!\n\n\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 MIDDLEWARE\n\n```python\nMIDDLEWARE = [\n [\"fastapi.middleware.trustedhost:TrustedHostMiddleware\", {\"allowed_hosts\": ALLOWED_HOSTS}],\n [\"fastapi.middleware.gzip:GZipMiddleware\", {\"minimum_size\": 1000, \"compresslevel\": 5}],\n ...\n [\"path:class\", {...kwargs}],\n]\n```\n\n#### routers.py\n\n\u042f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0431\u0443\u0434\u0443\u0449\u0438\u0445 APPs\n\n```python\nfrom fasttower.routers import APIRouter\n\nrouter = APIRouter(prefix=\"/api/v1\")\nrouter.include_router(APP_ROUTER, prefix='/app')\n```\n\n### \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\n\n\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\n\n```console \ntower g a appexample\n```\n\n\u041f\u043e\u0441\u043b\u0435 \u0435\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 **settings.py -> INSTALLED_APPS**\n\n```python\nINSTALLED_APPS = [\n 'fasttower.apps.taerich',\n 'fasttower.auth',\n ...\n 'appexample',\n]\n```\n\n\u041a\u0430\u0436\u0434\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 **config.py, models.py, admin.py, serializers.py, routers.py \u0438 views.py**\n\n#### Models\n\n\u041e\u0441\u043d\u043e\u0432\u0430\u043d\u043e \u043d\u0430 [tortoise](https://tortoise.github.io/), \u0442\u0430\u043a \u0447\u0442\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0435\u0439!\n\n```python\nfrom fasttower.db import models\n\n\nclass FastTowerModel(models.Model):\n say = models.CharField(max_length=100, default=\"Hello World!\")\n```\n\n#### Admin\n\n\u0422\u0443\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0434\u043b\u044f [\u0430\u0434\u043c\u0438\u043d \u043f\u0430\u043d\u0435\u043b\u0438](https://fastapi-admin-docs.long2ice.io/)\n\n```python\nfrom fastapi_admin.resources import Model, Dropdown\nfrom fasttower import admin\n\nfrom appexample import models\n\n\n@admin.site.app.register\nclass AppexampleTabMenu(Dropdown):\n label = \"Appexamples\"\n icon = \"fas fa-bars\"\n resources = []\n title = \"Appexamples\"\n```\n\n#### Views\n\n\u0422\u0443\u0442 \u0432\u0441\u0435 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e FastAPI, \u0441\u043a\u043e\u0440\u043e \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f **mixins** \u043a\u0430\u043a \u0432 Django \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u0445 **CRUD** \u0437\u0430\u0434\u0430\u0447!\n\n```python\nfrom appexample.models import FastTowerModel\n\nfrom fasttower.routers import APIRouter\n\nrouter = APIRouter()\n\n\n@router.get(\"/\")\nasync def say():\n return await FastTowerModel().create()\n```\n\n\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 **appexample.routers**, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0432 **example.routers**\n\n### Admin panel\n\n\u042f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439. \u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0434\u043b\u044f \u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f\n[**Redis**](https://github.com/redis/redis-py)\n\n\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0432 settings.py\n\n```\nADMIN_PANEL_REDIS = 'redis://localhost:6379/0'\n```\n\n\u0410 \u0442\u0430\u043a \u0436\u0435 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0435\u0433\u043e \u0432 asgi.py\n\n```python\nfrom fasttower.admin.site import app as admin_app, lifespan_admin\nfrom fasttower.db import lifespan\n\napp = FastTower(title=\"FastTower API Documentation\", lifespan=lifespans([lifespan, lifespan_admin]))\n\napp.mount('/admin', admin_app)\n\n```\n\n<details markdown=\"1\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434...</summary>\n```python\n\"\"\"\nASGI config for example project.\nIt exposes the ASGI callable as a module-level variable named ``application``.\n\"\"\"\nimport os\nfrom fasttower.utils import setup, lifespans\nos.environ.setdefault(\"FASTTOWER_SETTINGS_MODULE\", \"example.settings\")\nsetup()\nfrom fasttower.server import FastTower\nfrom example.routers import router\nfrom fasttower.admin.site import app as admin_app, lifespan_admin\nfrom fasttower.db import lifespan\napp = FastTower(title=\"FastTower API Documentation\", lifespan=lifespans([lifespan, lifespan_admin]))\napp.mount('/admin', admin_app)\napp.include_router(router)\n```\n</details>\n\n### Commands\n\n\u0421\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0438 \u0438\u0445 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0443\n\n```console\ntower --help\n```\n\n```text\n Usage: tower [OPTIONS] COMMAND [ARGS]... \n\n\u256d\u2500 Options \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e\n\u2502 --install-completion Install completion for the current shell. \u2502\n\u2502 --show-completion Show completion for the current shell, to copy it or customize the installation. \u2502\n\u2502 --help Show this message and exit. \u2502\n\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\n\u256d\u2500 Commands \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e\n\u2502 db Database commands \u2502\n\u2502 g Generate project structures and app components for FastTower. \u2502\n\u2502 run \u0417\u0430\u043f\u0443\u0441\u043a FastTower \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u2502\n\u2502 shell \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u0443\u044e \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443. \u2502\n\u2502 superuser Create a superuser. \u2502\n\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\n```\n\n#### \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434\n\n\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0444\u0430\u0439\u043b \u0432 \u043f\u0430\u043f\u043a\u0435 **app**(appexample) commands.py\n\n```python\nimport typer\n\nexample_commands = typer.Typer(name=\"appexample\", help=\"Example commands\")\n\n\n@example_commands.command()\ndef hello_world():\n print(\"Hello World!\")\n\n```\n\n\u0412\u043e\u0442 \u0438 \u0432\u0441\u0435 \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c!\n\n```console\ntower appexample hello-world\n```\n\n```console\nHello World!\n```\n\n\u0411\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e [Typer](https://typer.tiangolo.com/)\n\n## \u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442...",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Django-like framework built on FastAPI",
"version": "0.1.6",
"project_urls": {
"Bug Tracker": "https://github.com/pysashapy/fasttower/issues",
"Documentation": "https://pysashapy.github.io/fasttower",
"Homepage": "https://github.com/pysashapy/fasttower",
"Repository": "https://github.com/pysashapy/fasttower.git"
},
"split_keywords": [
"python",
" api",
" framework",
" web",
" rest",
" async",
" swagger",
" python3",
" asyncio",
" easy-web",
" starlette",
" fastapi",
" fasttower"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d0bfd4d66078d5efa9f0066d1ed15838a1325657f3af2f6bbd249da41ead2b32",
"md5": "b8a13622491cd144d788989568e38dae",
"sha256": "70c877bbcf9760fc7e0f2497ce7de9b5e1ba32bdb5a4c2164b6f982148221a6d"
},
"downloads": -1,
"filename": "fasttower-0.1.6-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b8a13622491cd144d788989568e38dae",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 37899,
"upload_time": "2024-11-11T12:38:04",
"upload_time_iso_8601": "2024-11-11T12:38:04.193496Z",
"url": "https://files.pythonhosted.org/packages/d0/bf/d4d66078d5efa9f0066d1ed15838a1325657f3af2f6bbd249da41ead2b32/fasttower-0.1.6-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3b859fcad6f255ea7fc30e4ca26e48868588308543f2132b4f380defcfed4d62",
"md5": "641715a48b8dce22f973e740a9429df3",
"sha256": "0d5116bd8cc59ec74cef5394274ca20dabc44247a55109d6ee41b9b48a12ff6f"
},
"downloads": -1,
"filename": "fasttower-0.1.6.tar.gz",
"has_sig": false,
"md5_digest": "641715a48b8dce22f973e740a9429df3",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 23094,
"upload_time": "2024-11-11T12:38:06",
"upload_time_iso_8601": "2024-11-11T12:38:06.136750Z",
"url": "https://files.pythonhosted.org/packages/3b/85/9fcad6f255ea7fc30e4ca26e48868588308543f2132b4f380defcfed4d62/fasttower-0.1.6.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-11 12:38:06",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "pysashapy",
"github_project": "fasttower",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [],
"lcname": "fasttower"
}