Python. Библиотека flask-sqlalchemy. Часть 1

Традиционно начинаем с установки библиотеки

pip install sqlalchemy

sqlalchemy — это пример ORM  (Object-Relational Mapping — объектно-реляционное отображение) — прослойки для работы с базой данных через объекты языка.

Создадим новостной сайт без особого дизайна, только функциональность, желающие могут навести красоту самостоятельно.  Итак опишу функциональность:

  1. Регистрация и авторизация.
  2. Гости видят список новостей и конкретную новость.
  3. Зарегистрированный пользователь может добавлять, редактировать и удалять свои записи.
  4. (*) Вывод списка статей с использованием пагинации.
  5. (*) Генерация БД.
  6. (*) Чат-бот отвечает на некоторые вопросы.

Иструментарий: python, субд sqlite — https://sqlitestudio.pl/index.rvt

1. Подготовка

Создадим вспомогательные папки db — для хранения базы данных, data — для хранения классов и вспомогательных файлов, первоначально создадим в ней 2 пустых файла users.py и news.py

В корневой папке создаем main.py со следующим содержанием (раскомментированным):

from flask import Flask
from data import db_session # Грузим из нашей папки data

app = Flask(__name__)
app.config['SECRET_KEY'] = 'sgu_secret_key'


def main():
    db_session.global_init("db/news.sqlite") # При первом запуске будет создан файл news.sqlite
    app.run()


if __name__ == '__main__':
    main()

В папке data создаем файл db_session.py:

import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base  

SqlAlchemyBase = declarative_base() #абстрактная база для наследования моделей

__factory = None # переменная для работы с сессиями


def global_init(db_file):
    global __factory

    if __factory: #если сессия уже создана, то выходим
        return

    if not db_file or not db_file.strip():
        raise Exception("Надо задать имя файла базы данных.")

    conn_str = f'sqlite:///{db_file.strip()}?check_same_thread=False' #дополнительный параметр указан 
							#	для разрешения множественного доступа
    print(f"Подключение к базе данных по адресу {conn_str}") #Выводим сообщение для информирования пользователя

    engine = sqlalchemy.create_engine(conn_str, echo=False) # Falseотключает вывод SQL-запросов в консоль
    __factory = sqlalchemy.orm.sessionmaker(bind=engine)

    # Подгружаем здесь все дополнительные классы. Классы храним в этой же папке с одноименными названиями 
    # и расширением py. Первоначально эти файлы пустные
    from . import users
    from . inport rubriks
    from . import news

    SqlAlchemyBase.metadata.create_all(engine)


def create_session() -> sqlalchemy.orm.Session:
    global __factory
    return __factory()

В результате запуска main.py создается файл news.sqlite

 

2. База данных

Рассмотрим базу из трех таблиц (в скобках указаны поля):

  • users (idu,name,email,hash_pass,cdate);
  • news(idn,title,shrt_text,full_text,ndate,idu,idr);
  • rubrics(idr,rubrik).

Для каждой таблицы сделаем одноименные классы. При этом с использованием ORM нет необходимости использовать SQL.

Далее заполоняем 3 файла, генерирующие таблицы

news.py

import datetime
import sqlalchemy
from werkzeug.security import generate_password_hash, check_password_hash

from .db_session import SqlAlchemyBase


class News(SqlAlchemyBase):  # наследуем на основе класса SqlAlchemyBase
    __tablename__ = 'news'

    idn = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True)
    title = sqlalchemy.Column(sqlalchemy.String, nullable=True)
    short_text = sqlalchemy.Column(sqlalchemy.String, index=True, unique=True, nullable=True)
    full_text = sqlalchemy.Column(sqlalchemy.String, index=True, unique=True, nullable=True)
    hash_pass = sqlalchemy.Column(sqlalchemy.String, nullable=True)
    ndate = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now)
    idu = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("users.idu"))
    user = sqlalchemy.orm.relation('User')
    idr = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("rubriks.idr"))
    rubrik = sqlalchemy.orm.relation('Rubrik')

rubriks.py

import sqlalchemy

from .db_session import SqlAlchemyBase


class Rubrik(SqlAlchemyBase):
    __tablename__ = 'rubriks'
    idr = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, 
                           autoincrement=True)
    rubrik = sqlalchemy.Column(sqlalchemy.String, nullable=True)

users.py

import datetime
import sqlalchemy
from werkzeug.security import generate_password_hash, check_password_hash

from .db_session import SqlAlchemyBase


class User(SqlAlchemyBase):  # наследуем на основе класса SqlAlchemyBase
    __tablename__ = 'users'

    idu = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True)
    name = sqlalchemy.Column(sqlalchemy.String, nullable=True)
    email = sqlalchemy.Column(sqlalchemy.String, index=True, unique=True, nullable=True)
    hash_pass = sqlalchemy.Column(sqlalchemy.String, nullable=True)
    сdate = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now)
    news = sqlalchemy.orm.relation("News", back_populates='user')

    def __repr__(self):
        return f'Пользователь:  {self.idu} {self.name}'

    def set_password(self, password):
        self.hashed_password = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.hashed_password, password)
Поделиться:
  • Добавить ВКонтакте заметку об этой странице
  • Мой Мир
  • Facebook
  • Twitter
  • LiveJournal
  • FriendFeed
  • В закладки Google
  • Google Buzz
  • Яндекс.Закладки
  • StumbleUpon
  • Technorati
  • БобрДобр
  • Memori.ru
  • МоёМесто.ru

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.