Flask на виртуальном хостинге Beget

2022-04-25

Мой сайт, который собирает статистику по файлам пользователей проекта DCS работает на хостинге Beget и написан с ипользованием Python и фреймворка Flask. Как установить Python и фреймворк написано в статье тут. Я же покажу как я настроил сам фреймворк.

Структура проекта

├── HelloFlask
│   ├── blueprints
│   │   └── blogapp
│   ├── config.py
│   ├── controllers.py
│   ├── __init__.py
│   ├── logs
│   ├── models.py
│   ├── profs
│   ├── static
│   │   ├── files
│   │   ├── img
│   │   ├── styles
│   ├── templates
│   └── view.py
├── passenger_wsgi.py
├── public -> public_html/
├── public_html
├── README.md
├── requirements.txt
├── run.py
├── tmp
│   └── restart.txt
└── venv

Содержимое файлов настроек

congig.py

Файл конфигурации позволяет гибко настраивать фреймворк. Логирование настроено на запись логов в файл в директорию log. Также при оптимизации сайта понадобилось настройить сохранение .prof файлов профилировщика на диск в директорию profs.

class Configuration:
    DEBUG = False
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    SQLALCHEMY_DATABASE_URI = 'mysql://<username>:<password>@127.0.0.1:3306/<db_name>'
    TESTING = False
    PROFILING = False  # Enable profiling
    LOGGING = True  # Enabe logging
    CACHE_TYPE = 'SimpleCache'  # Flask-Caching related configs
    CACHE_DEFAULT_TIMEOUT = 300


class ProductionConfiguration(Configuration):
    pass


class TestConfiguration(Configuration):
    TESTING = True


class DevelopmentConfiguration(Configuration):
    DEBUG = True

__init__.py

Для инициализации использована фабричная функция.

import os

import logging
from logging.handlers import RotatingFileHandler

from flask import Flask, render_template
from werkzeug.middleware.profiler import ProfilerMiddleware


# Import SQLAlchemy
from flask_sqlalchemy import SQLAlchemy

from .config import (DevelopmentConfiguration, ProductionConfiguration,
                     TestConfiguration)

from flask_caching import Cache

cache = Cache()
db = SQLAlchemy(engine_options={'connect_args': {'connect_timeout': 10}})


def create_app():
    # Define the WSGI application object
    app = Flask(__name__)

    # Configurations
    try:
        if os.environ['FLASK_ENV'] == 'development':
            app.config.from_object(DevelopmentConfiguration)
        elif os.environ['FLASK_ENV'] == 'testing':
            app.config.from_object(TestConfiguration)
    except KeyError:
        app.config.from_object(ProductionConfiguration)
    if app.config.get('PROFILING'):
        if not os.path.exists('HelloFlask/profs'):
            os.mkdir('HelloFlask/profs')
        app.wsgi_app = ProfilerMiddleware(
                app.wsgi_app,
                restrictions=(
                    '/controllers.py:',
                    [30],
                    ),
                profile_dir=os.path.join('HelloFlask', 'profs'),
                filename_format='{path}-{time:.0f}.prof',
                )
    if app.config.get('LOGGING'):
        if not os.path.exists('HelloFlask/logs'):
            os.mkdir('HelloFlask/logs')
        file_handler = RotatingFileHandler(
                'HelloFlask/logs/hello-flask.log',
                maxBytes=10240,
                backupCount=10)
        file_handler.setFormatter(logging.Formatter(
         '%(asctime)s:%(levelname)s:%(message)s:%(pathname)s:%(lineno)d')
        )
        file_handler.setLevel(logging.INFO)
        app.logger.addHandler(file_handler)

        app.logger.setLevel(logging.INFO)
        app.logger.info('Startup logging')

    # Define the database object which is imported
    # by modules and controllers
    db.init_app(app)

    cache.init_app(app)

    with app.app_context():
        db.create_all()

    # HTTP error handling
    @app.errorhandler(404)
    def not_found(error):
        return render_template('page404.html'), 404

    # Import a module/component using its blueprint handler variable (mod_auth)
    from HelloFlask.view import webapp
    from HelloFlask.blueprints.blogapp.view import posts

    # Register blueprint(s)
    app.register_blueprint(webapp)
    app.register_blueprint(posts)

    # Build the database:
    # This will create the database file using SQLAlchemy
    with app.app_context():
        db.create_all()

    migrate = Migrate(app, db)

    return app


app = create_app()


if __name__ == '__main__':
    app.run()

passenger_wsgi.py

  # -*- coding: utf-8 -*-
  # /home/m/ma5tad/dcs-webapp-flask/public_html/venv/bin/flask
  import sys
  sys.path.append('/home/m/ma5tad/dcs-webapp-flask/HelloFlask') # указываем директорию с проектом
  sys.path.append('/home/m/ma5tad/dcs-webapp-flask/venv/lib/python3.6/site-packages') # указываем директорию с библиотеками, куда поставили Flask

  # from public_html.HelloFlask import create_app as application # когда Flask стартует, он ищет application. Если не указать 'as application', сайт не заработает
  from HelloFlask import app as application # когда Flask стартует, он ищет application. Если не указать 'as application', сайт не заработает
  from werkzeug.debug import DebuggedApplication # Опционально: подключение модуля отладки
  application.wsgi_app = DebuggedApplication(application.wsgi_app, True) # Опционально: включение модуля отадки
  application.debug = False  # Опционально: True/False устанавливается по необходимости в отладке

run.py

from HelloFlask import create_app


def main(*args, **kwargs):
    app = create_app(*args, **kwargs)
    return app


if __name__ == '__main__':
    APP = main()
    APP.run(host='127.0.0.1', port=9000)

Сайт расположен на домене ma5ta.ru. Изначально сайт располагался на VPS Hetzner. При переезде на Бегет пришлось сменить БД и модифицировать работу сайта.