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

from project import create_app

app = create_app()

Также импортируем пакет db в файле base.py.

Наконец, удалим переменную среды FLASK_APP из файла docker-

compose-dev.yml:

environment:

-FLASK_DEBUG=1

-APP_SETTINGS=project.config.DevelopmentConfig

-DATABASE_URL=postgres://postgres:postgres@usersdb:5432/users_dev

-DATABASE_TEST_URL=postgres://postgres:postgres@usersdb:5432/users_test

Выполним контрольную проверку текущей версии приложения:

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

run users python manage.py recreate_db

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

1.6. СОЗДАНИЕ RESTFUL-МАРШРУТОВ

Создадим три новых маршрута, следуя лучшим практикам архитектурно-

го стиля RESTful, с использованием принципов разработки через тестирование

(Test-driven development, TDD). Новые маршруты перечислены в таблице ниже:

Точка доступа

HTTP-метод

CRUD-метод

Результат

 

 

 

 

/users

GET

READ

Получение данных всех

 

 

 

пользователей

/users/:id

GET

READ

Получение данных одного

 

 

 

пользователя

/users

POST

CREATE

Добавление пользователя

Далее для каждого из новых маршрутов мы выполним следующие дейст-

вия:

1)создадим тесты;

2)выполним тесты и увидим неудачные результаты («красный цвет» со-

гласно методологии TDD);

3) напишем необходимый код для получения успешного результата тес-

тов («зелёный цвет» согласно методологии TDD);

4) выполним рефакторинг кода (при необходимости).

20

1.6.1. МАРШРУТ POST /USERS

Начнём с создания POST-маршрута. Добавим тест в класс

TestUserService() в файл project/tests/test_users.py:

def test_add_user(self):

"""Проверка, что в базу данных можно добавить нового пользовате-

ля."""

with self.client:

response = self.client.post( '/users', data=json.dumps({

'username': 'testname1',

'email': 'testname1@flaskapp.org' }), content_type='application/json', )

data = json.loads(response.data.decode()) self.assertEqual(response.status_code, 201) self.assertIn('testname1@flaskapp.org was added!', da-

ta['message'])

self.assertIn('success', data['status'])

Затем добавим обработчик маршрута в файл project/api/users.py

@users_blueprint.route('/users', methods=['POST']) def add_user():

post_data = request.get_json() username = post_data.get('username') email = post_data.get('email')

db.session.add(User(username=username, email=email)) db.session.commit()

response_object = { 'status': 'success',

'message': f'{email} was added!'

}

return jsonify(response_object), 201

Также обновим импорт:

from flask import Blueprint, jsonify, request from project.api.models import User

from project import db

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

Ran 5 tests in 0.092s

OK

21

А что насчёт ошибок и исключений? Рассмотрим следующие варианты.

1.Полезная нагрузка не была отправлена.

2.Полезная нагрузка некорректна, т.е. объект JSON пустой или содер-

жит неправильные ключи.

3. Пользователь уже существует в базе данных.

Добавим несколько тестов для случаев, перечисленных выше:

def test_add_user_invalid_json(self):

"""Проверка, что выдается ошибка, если объект JSON пуст.""" with self.client:

response = self.client.post( '/users', data=json.dumps({}),

content_type='application/json',

)

data = json.loads(response.data.decode()) self.assertEqual(response.status_code, 400) self.assertIn('Invalid payload.', data['message']) self.assertIn('fail', data['status'])

def test_add_user_invalid_json_keys(self):

"""Проверка, что выдаётся ошибка, если объект JSON не имеет клю-

ча username.""" with self.client:

response = self.client.post( '/users',

data=json.dumps({'email': 'testname1@flaskapp.org'}), content_type='application/json',

)

data = json.loads(response.data.decode()) self.assertEqual(response.status_code, 400) self.assertIn('Invalid payload.', data['message']) self.assertIn('fail', data['status'])

def test_add_user_duplicate_email(self):

"""Проверка, что выдаётся ошибка, если адрес электронной почты уже существует."""

with self.client: self.client.post(

'/users',

data=json.dumps({

22

'username': 'testname1',

'email': 'testname1@flaskapp.org' }), content_type='application/json',

)

response = self.client.post( '/users', data=json.dumps({

'username': 'testname1', 'email': 'testname1@flaskapp.org'

}), content_type='application/json',

)

data = json.loads(response.data.decode()) self.assertEqual(response.status_code, 400) self.assertIn(

'Sorry. That email already exists.', data['message']) self.assertIn('fail', data['status'])

Убедимся, что тесты после запуска завершаются неудачно, а затем обно-

вим обработчик маршрута:

@users_blueprint.route('/users', methods=['POST']) def add_user():

post_data = request.get_json() response_object = {

'status': 'fail',

'message': 'Invalid payload.'

}

if not post_data:

return jsonify(response_object), 400 username = post_data.get('username') email = post_data.get('email')

try:

user = User.query.filter_by(email=email).first() if not user:

db.session.add(User(username=username, email=email)) db.session.commit()

response_object['status'] = 'success' response_object['message'] = f'{email} was added!' return jsonify(response_object), 201

else:

23

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