В предыдущих "сериях"

Часть 1

Часть 2

Содержание

Вместо введения

Эта часть будет практической, если помните я решил углубиться в React и Flask. Поэтому при помощи ИИ начинаю. Нет, ИИ не будет делать за меня весь проект, он будет выполнять функцию наставника. Ну и иногда чернорабочего (как, например, собрать файл SQL для инициирования БД) для ускорения ручного труда.

Родилась у меня идея сделать симулятор торговли на Московской бирже. Зачем и почему не спрашивайте – это было давно, просто сейчас дозрело. И, как мне кажется, в качестве учебного проекта вполне подойдёт.

После обсуждения с ИИ самой идеи, пришёл к следующей концепции по её реализации: 

Бэкенд

Flask SQLAlchemy

Фронтенд

React + Vite

СУБД

MySQL

Конечно, по дороге ИИ мне наговорил кучу новых слов типа Zustand, Alembic, TanStack, axios. Доверимся ему, и в ходе написания кода будем смотреть, что и с чем едят.

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

Итак, приступим

Flask

Сам Flask я уже запускал не reg.ru. Если следовать чётко инструкции, то passenger_wsgi.py и файл проекта лежат в корне. Вроде бы нет проблем, но для деплоя у меня используется GitHub Actions, в частности конкретно за загрузку отвечает SamKirkland/FTP-Deploy-Action. А он чистит целевую папку перед аплоадом, и надо прописывать исключения. При помощи бубна (подсказок ИИ) и метода «научного тыка» (ведь не всё, что говорит ИИ, запускается 100% сразу) получилось перенести весь питон в /app. Еще мне не понравилось, что passenger_wsgi.py содержит имя пользователя в открытом виде (у меня ж всё в GitHub уходит), поэтому захотел вынести в .env.

Вот что получилось:

passenger_wsgi.py (лежит в корне)
import sys
import os

def read_env(path):
    if not os.path.exists(path):
        return
    with open(path) as f:
        for line in f:
            line = line.strip()
            if not line or line.startswith('#') or '=' not in line:
                continue
            key, val = line.split('=', 1)
            value = val.strip().strip("'").strip('"')
            os.environ.setdefault(key.strip(), value)
read_env(os.path.join(os.path.dirname(__file__), '.env'))

INTERP = os.getenv('PYTHON_INTERP')
if sys.executable != INTERP:
   os.execl(INTERP, INTERP, *sys.argv)

sys.path.append(os.getcwd())

from app import create_app
application = create_app()

if __name__ == "__main__":
   application.run(host='0.0.0.0')

Кстати, функцию read_env() пришлось заставлять писать ИИ (я совсем пока не крут в python). Но интересно другое: сперва он мне предложил сделать через dotenv, но надо убедиться, что он есть до загрузки моего окружения. Конечно, его нет по умолчанию. Тогда он начал предлагать разные костыли, чтоб не грузить файл в GitHub и сохранить имя пользователя в нём. Пришлось напомнить, что раз .env есть, то можно его и прочитать. Собственно вот.

Окружение .env
PYTHON_INTERP=/flaskenv/bin/python
DB_URL=mysql+mysqldb://dbuser:dbpass@localhost/dbname
JWT_SECRET=SECRET
ALLOWED_ORIGIN=https://HOST.ru

Остальные строки уже на будущее

__init__.py (лежит в /app)
import os
from flask import Flask

def create_app():
    app = Flask(__name__)

    @app.route('/api/ping')
    def ping():
        return {'status': 'ok'}

    return app

Ну тут пока всё упростил до минимума, чтобы проверить запустится или нет.

Кстати, пока ковырялся, подправил скрипт для деплоя, чтобы он всегда закидывал .restart-app (файл нужен для перезапуска Flask через passenger_wsgi).

Всё, Flask на поддомене заработал. Можно приступать к дальнейшим шагам.

Python окружение

Подключился по SSH к серверу, и по совету ИИ, установил следующее в своё окружение.

Запуск окружения
source flaskenv/bin/activate

Делал всё по одному, для наглядности. Не до конца понимаю, что и в какой момент я буду использовать, и как это будет выглядеть в коде. Хотя в целом общее представление есть.

Установка пакетов
pip install flask-sqlalchemy
pip install flask-migrate
pip install flask-jwt-extended
pip install mysqlclient
pip install requests
pip install python-dotenv
pip install bcrypt
pip install marshmallow
pip install flask-cors

Ну и под конец.

Сохраняю requirements.txt
pip freeze > requirements.txt

Единственное, но об этом я подумал уже после, может стоило создать отдельное окружение. Есть совет? Как лучше поступить: иметь одно окружение на все проекты, или для каждого делать отдельно?

MySQL

Ну с MySQL всё намного проще. Во-первых, она уже есть на хостинге, к ней также стоит phpMyAdmin. А, во-вторых, с MySQL я знаком давно и достаточно неплохо, что-то, возможно, и не помню, но это мелочи.

Так как структура уже продумана (с формализацией и нормализацией у меня проблем замечено не было), попросил ИИ сделать скрипт создания таблиц. И, собственно, выполнил его на сервере.

Последние штрихи

После успешного выполнения всего описанного повторил это на локальной машине, с той лишь разницей, что пришлось сделать еще один файлик run.py для локального запуска.

run.py (только локально)
import sys
import os

from app import create_app
application = create_app()

if __name__ == "__main__":
   application.run(host='0.0.0.0')

Залил всё на GitHub. Сделал деплой (по аналогии с прошлым проектом). И… снёс прошлый проект на сервере. Нужно внимательнее делать копипаст, но ничего всё восстановил, переписал. И… вуаля. Теперь всё работает.

Вместо заключения

Выводы какие-то делать ещё рано. Пока только готова инфраструктура для backend-разработки, которая соответствует задуманной концепции. Связь ПК-> GitHub -> сервер выстроена, так что можно писать сам код.

Вот, вроде с виду простенький урок у меня вышел, но занял достаточно времени, и позволил узнать немного нового, а также закрепить некоторые старые знания.

P.S.: Кто знает где найти логи python на shared reg.ru? Всё облазил - не сообразил. Просто, когда python падает приходится не по логам искать, а методом выбрасывания кусков кода.

Комментарии (4)


  1. Junecat
    29.04.2026 15:16

    Вот я внимательно читаю всю серию, начиная с первой статьи

    И сейчас созрел вопрос: а это вообще про что?

    Потому что сейчас вы просто пересказываете то, что наговорила вам нейросеть, без особых объяснений. То есть, «если я выберу точно такой же стек, то я могу как обезьяна набрать те же команды, и получить тот же результат»?

    Так я могу сам у нейросети спросить…


    1. VAnderskaeV Автор
      29.04.2026 15:16

      Это про путь. Не тот, который “смотрите, я стал синьором за 6 месяцев, если хотите как я - подписывайтесь”, а про тот, когда я аыбрал направление и иду. Возможно такой вариант и не обречён на успех, а может и наоборот. В любом случае, я уверен, не один я выбрал подобный путь и кому-то станет этот опыт полезным.

      А вообще, если абстрагироваться от ИИ и программирования, процесс обучения так и строится: сперва просто механическое повторение, попытки понять почему так, и только со временем и опытом получается выдать что-то своё.

      Возьмём эту же статью. Конечно, может показаться, что вбил запрос - получил список команд, ввел их все и готово. Но всё не так, и об этом сказано. Не всё, что выдал ИИ сработало в конкретной ситуации. В некоторых местах пришлось его подкорректировать. Где-то просто захотелось сделать по-своему.

      К примеру, вынесение того же имени пользователя в .env. Или запуск Flask из поддиректории. Соглашусь, может и не много, но и я только изучаю python. А это всего лишь первые шажки.


  1. Jack444
    29.04.2026 15:16

    Flask в 2026 году, МОЩНО!


    1. VAnderskaeV Автор
      29.04.2026 15:16

      Тезисность в 2026 году, ЖИДКО. Хотя мной описано почему я выбрал Flask, всё же покапаю в стороную возможности запуска FastAPI на том что есть (Django точно не встанет). Других альтернатив я пока не знаю. Если что-то имелось другое ввиду, пардоньте, гадать не обучен.