# Подключение Flask-приложения к базе данных PostgreSQL

В отличие от Django — фрэймворка для создания больших и комплексных сайтов на Python — Flask предназначен для решения более локальных задач, создания более компактных сайтов и приложений. Django по умолчанию устанавливает и использует SQLite для базовой работы с данными, у Flask же нет встроенного инструмента для работы с базами данных.

В этой инструкции мы расскажем, как подключить к Flask-приложению базу данных PostgreSQL.

# О создаваемом приложении

Создавать приложение будем на локальной машине, затем развернём его непосредственно на Джино.Хостинге.

Большинство современных IDE имеют встроенные инструменты для деплоя проекта на сервер, поэтому нет принципиальной разницы, какую IDE использовать. Развёртывание проектов на Хостинге из Visual Studio Code и PyCharm мы описывали отдельно.

Для демонстрации работы баз данных с Flask мы создадим приложение со списком книг и их описанием.

# Подготовка хостинга

# Подключение услуг

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

В разделе Услуги подключим поддержку веб-приложений, баз данных PostgreSQL и SSH:

«flask_db»

# Создание базы данных

Создадим новую базу для работы с приложением. Для этого перейдём в раздел УправлениеУправление PostgreSQL и нажмём кнопку Создать базу данных:

«flask_db»

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

# Создание виртуального окружения

После этого подключимся к хостингу по SSH и создадим виртуальное окружение, с которым впоследствии будет работать наше приложение:

/opt/alt/python37/bin/virtualenv --python /opt/alt/python310/bin/python3 venv310

Здесь /opt/alt/python310/bin/python3 — путь к интерпретатору Python 3.10. Если вы планируете использовать другую версию Python со своим приложением, путь к нужному интерпретатору Python, а также список всех доступных версий можно посмотреть в разделе УправлениеТехническая информация.

После создания виртуального окружения активируем его:

source ./venv310/bin/activate

Теперь установим в него все необходимые для работы приложения пакеты — непосредственно Flask и агент для подключения к PostgreSQL — psycopg2:

pip install flask psycopg2-binary

Хостинг готов! Переходим к созданию приложения.

# Создание приложения

Переходим на локальную машину и запускаем IDE. Создаём новое виртуальное окружение для работы с приложением и в уже активированном виртуальном окружении создаём основной файл приложения app.py:

import os
import psycopg2
from flask import Flask, render_template

app = Flask(__name__)

def get_db_connection():
    conn = psycopg2.connect(host='localhost',
                            database='flask_db',
                            user=os.environ['DB_USERNAME'],
                            password=os.environ['DB_PASSWORD'])
    return conn


@app.route('/')
def index():
    conn = get_db_connection()
    cur = conn.cursor()
    cur.execute('SELECT * FROM books;')
    books = cur.fetchall()
    cur.close()
    conn.close()
    return render_template('index.html', books=books)

Здесь мы подключаем к приложению Flask и psycopg2 — фрэймворк и агент для взаимодействия Flask с PostgreSQL.

В блоке def get_db_connection(): указываем параметры для подключения к локальной базе данных.

Следующий шаг — создание файла, работающего с базами данных — init_db.py:

init_db.py

init_db.py

import os
import psycopg2

conn = psycopg2.connect(
        host="localhost",
        database="flask_db",
        user=os.environ['DB_USERNAME'],
        password=os.environ['DB_PASSWORD'])

cur = conn.cursor()

cur.execute('DROP TABLE IF EXISTS books;')
cur.execute('CREATE TABLE books (id serial PRIMARY KEY,'
                                 'title varchar (150) NOT NULL,'
                                 'author varchar (50) NOT NULL,'
                                 'pages_num integer NOT NULL,'
                                 'review text,'
                                 'date_added date DEFAULT CURRENT_TIMESTAMP);'
                                 )


cur.execute('INSERT INTO books (title, author, pages_num, review)'
            'VALUES (%s, %s, %s, %s)',
            ('A Tale of Two Cities',
             'Charles Dickens',
             489,
             'A great classic!')
            )


cur.execute('INSERT INTO books (title, author, pages_num, review)'
            'VALUES (%s, %s, %s, %s)',
            ('Anna Karenina',
             'Leo Tolstoy',
             864,
             'Another great classic!')
            )

conn.commit()

cur.close()
conn.close()

Здесь мы описываем создание новой таблицы в базе, название её строк и столбцов, а также заполняем первые две строки данными.

После этого создадим шаблоны, в которых будет отображаться информация из базы.

В папке с нашим приложением создадим папку templates и в неё добавим файл base.html:

base.html

base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %}- FlaskApp</title>
    <style>
        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }

        .book {
            padding: 20px;
            margin: 10px;
            background-color: #f7f4f4;
        }

        .review {
                margin-left: 50px;
                font-size: 20px;
        }

    </style>
</head>
<body>
    <nav>
        <a href="{{ url_for('index') }}">FlaskApp</a>
        <a href="#">About</a>
    </nav>
    <hr>
    <div class="content">
        {% block content %} {% endblock %}
    </div>
</body>
</html>

Это базовый шаблон, который описывает вывод данных из базы. Также в папку с шаблонами добавим индексный файл, который и будет отображать данные из шаблона:

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Books {% endblock %}</h1>
    {% for book in books %}
        <div class='book'>
            <h3>#{{ book[0] }} - {{ book[1] }} BY {{ book[2] }}</h3>
            <i><p>({{ book[3] }} pages)</p></i>
            <p class='review'>{{ book[4] }}</p>
            <i><p>Added {{ book[5] }}</p></i>
        </div>
    {% endfor %}
{% endblock %}

Приложение готово. Теперь нужно загрузить его на сервер и настроить работу с установленной на хостинге PostgreSQL.

# Развёртывание проекта на хостинге

После завершения работы с приложением загрузим его на сервер. Это можно сделать любым удобным для вас способом.

Папку с приложением нужно разместить в папке domains в подпапке с доменным именем, на котором будет запускаться приложение, например: ~/domains/example.com.

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

# Подключение проекта к базе данных

В качестве базы данных мы использовали PostgreSQL. На Джино к PostgreSQL можно подключаться только по имени сервера (узнать свой технический домен можно в разделе настроек хостинг-контейнера УправлениеТехническая информация.), поэтому исправим параметры для подключения к базе в файле app.py:

def get_db_connection():
    conn = psycopg2.connect(host='postgresql.j12345678.myjino.ru',
                            database='j12345678_fl',
                            user="j12345678_fl",
                            password="password")
    return conn
…

Также поправим файл init_db.py:

…
conn = psycopg2.connect(
        host="postgresql.j12345678.myjino.ru",
        database="j12345678_fl",
        user="j12345678_fl",
        password="password")

Имя сервера для подключения к PostgreSQL можно узнать в разделе УправлениеТехническая информация.

После изменения параметров подключения заполним новую базу данными из файла init_db.py:

python init_db.py

Далее зададим переменные среды для запуска нашего приложения:

export FLASK_APP=app
export FLASK_ENV=development

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

# Запуск приложения

Хостинг на Джино использует в качестве веб-сервера Apache с модулем mod_passenger — для запуска приложения нам понадобится файл passenger_wsgi.py. Он должен находиться в папке домена, на котором будет запускаться приложение (~/domains/example.com/passenger_wsgi.py).

Содержимое файла должно быть следующим:

import sys, os

INTERP = os.path.expanduser("~/venv310/bin/python3")

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

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

from flask_app.app import app as application

В этом файле мы указываем путь к файлу, запускающему виртуальное окружение ("~/venv310/bin/python3"), и указываем Passenger — веб-серверу — основной файл нашего приложения (from flask_app.app…).

После создания passenger_wsgi.py его нужно сохранить и перезагрузить веб-сервер в разделе УправлениеНастройки веб-сервера.

Теперь главная страница вашего сайта должна выглядеть примерно так:

«flask_db»