Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Разработка веб-приложений с использованием фреймворка Flask. В 2 частях. Ч.2. Учебное пособие-1.pdf
Скачиваний:
2
Добавлен:
06.09.2026
Размер:
421 Кб
Скачать
☆

3.РАЗВИТИЕ ПРИЛОЖЕНИЯ

Втретьей части мы добавим миграции базы данных вместе с функцией хеширования паролей для реализации аутентификации на основе токенов для сервиса, отвечающего за регистрацию пользователей с помощью веб-токенов

JSON (JSON Web Tokens, JWT).

3.1.ПАКЕТ FLASK MIGRATE

Вэтом параграфе мы используем библиотеку Flask Migrate для обработки миграций базы данных.

Установим среду testdriven-dev в качестве активной для Docker Machine:

$ docker-machine env testdriven-dev

$ eval $(docker-machine env testdriven-dev)

Обновим контейнеры:

$ docker-compose -f docker-compose-dev.yml up -d

Убедимся, что приложение работает в браузере, а затем запустим тесты:

$ docker-compose -f docker-compose-dev.yml \ run users python manage.py test

$ docker-compose -f docker-compose-dev.yml \ run client npm test

3.1.1. ИЗМЕНЕНИЕ МОДЕЛИ

Внесём несколько изменений в схему в services/users/project/api/ models.py.

1.Поле username в модели должно быть уникальным.

2.Поле email в модели должно быть уникальным.

Также добавим поле password (в следующем параграфе), которое будет хешировано перед добавлением в базу данных:

password = db.Column(db.String(255), nullable=False)

Пока не вносите никаких изменений. Начнём с тестов. Добавим новый файл в services/users/project/tests с именем test_user_model.py. Этот файл будет содержать тесты, связанные с моделью базы данных:

import unittest

40

from project import db

from project.api.models import User

from project.tests.base import BaseTestCase

class TestUserModel(BaseTestCase):

def test_add_user(self): user = User(

username='justatest',

email='test@test.com',

)

db.session.add(user)

db.session.commit()

self.assertTrue(user.id) self.assertEqual(user.username, 'justatest') self.assertEqual(user.email, 'test@test.com') self.assertTrue(user.active)

def test_add_user_duplicate_username(self): user = User(

username='justatest',

email='test@test.com',

)

db.session.add(user)

db.session.commit() duplicate_user = User(

username='justatest',

email='test@test2.com',

)

db.session.add(duplicate_user) self.assertRaises(IntegrityError, db.session.commit)

def test_add_user_duplicate_email(self): user = User(

username='justatest',

email='test@test.com',

)

db.session.add(user)

db.session.commit()

41

duplicate_user = User( username='justanothertest', email='test@test.com', )

db.session.add(duplicate_user) self.assertRaises(IntegrityError, db.session.commit)

def test_to_json(self): user = User(

username='justatest',

email='test@test.com',

)

db.session.add(user)

db.session.commit() self.assertTrue(isinstance(user.to_json(), dict))

if __name__ == '__main__': unittest.main()

Обратите внимание, что мы не вызывали метод db.session.commit() во второй раз при добавлении пользователя. Вместо этого мы передали и db.session.commit в метод assertRaises() и позволили методу assertRaises() вызы-

вать его и произвести появление исключения.

Не стоит забывать, что вместо этого можно использовать assertRaises в

качестве менеджера контекста:

with self.assertRaises(IntegrityError):

db.session.commit()

Добавим импорт:

from sqlalchemy.exc import IntegrityError

Запустим тесты. Вы должны увидеть сообщения о двух ошибках:

test_add_user_duplicate_email (test_user_model.TestUserModel) ...

FAIL test_add_user_duplicate_username (test_user_model.TestUserModel) ... FAIL

Сама ошибка:

NameError: name 'add_user' is not defined

AssertionError: IntegrityError not raised by do

AssertionError: IntegrityError not raised by do

42

3.1.2. НАСТРОЙКА FLASK MIGRATE

Поскольку нужно изменить схему базы данных, добавим Flask-Migrate в

файл requirements.txt:

flask-migrate==2.1.1

В файл services/users/project/__init__.py добавим импорт, создадим новый

экземпляр и обновим функцию create_app():

# services/users/project/__init__.py

import os

from flask import Flask

from flask_sqlalchemy import SQLAlchemy

from flask_debugtoolbar import DebugToolbarExtension from flask_cors import CORS

from flask_migrate import Migrate

# инстанционирование расширений db = SQLAlchemy()

toolbar = DebugToolbarExtension() migrate = Migrate()

def create_app(script_info=None):

# инстанционирование приложения app = Flask(__name__)

#включение CORS CORS(app)

#подключение конфигурации

app_settings = os.getenv('APP_SETTINGS') app.config.from_object(app_settings)

# запуск расширений db.init_app(app) toolbar.init_app(app) migrate.init_app(app, db)

43

# регистрация blueprints

from project.api.users import users_blueprint app.register_blueprint(users_blueprint)

# контекст оболочки для flask cli app.shell_context_processor({'app': app, 'db': db}) return app

Прежде чем создавать миграции, обновим файл .dockerignore:

env

htmlcov

.dockerignore

Dockerfile-dev

Dockerfile-prod

migrations

Затем обновим контейнеры:

$ docker-compose -f docker-compose-dev.yml up -d --build

Создадим каталог миграции, добавим начальную миграцию, а затем при-

меним её к базе данных:

$ docker-compose -f docker-compose-dev.yml \ run users python manage.py db init

$ docker-compose -f docker-compose-dev.yml

\run users python manage.py db migrate $ docker-compose -f docker-compose-dev.yml

\run users python manage.py db upgrade

Теперь мы можем внести изменения в схему:

class User(db.Model): __tablename__ = "users"

id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(128), unique=True, nullable=False) email = db.Column(db.String(128), unique=True, nullable=False) active = db.Column(db.Boolean, default=True, nullable=False)

Снова выполним команды:

$ docker-compose -f docker-compose-dev.yml

\run users python manage.py db migrate $ docker-compose -f docker-compose-dev.yml

\run users python manage.py db upgrade

44

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]