Python: Веб-разработка (Flask)

Теория: CRUD

Практически всю веб-разработку можно свести к CRUD-операциям. CRUD — широко распространенный термин, который означает четыре стандартные операции над любой сущностью. В этом уроке познакомимся с CRUD-операциями, которые считаются типичными для веб-разработки.

Операции CRUD

CRUD — это акроним, который обозначает четыре операции над сущностями веб-разработки по первым буквам их названий:

  • Create — создание
  • Read — чтение
  • Update — обновление
  • Delete — удаление

Например, в случае с пользователем можно составить такое соответствие:

Create

  • Регистрация

Read

  • Просмотр профиля пользователями сайта
  • Просмотр пользователя в административном интерфейсе

Update

  • Обновление личных данных
  • Смена емейла
  • Смена пароля

Delete

  • Удаление

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

Создание полного круда включает в себя следующие действия:

  • Создание сущности в коде
  • Добавление таблицы в базу
  • Написание тестов на обработчики
  • Добавление обработчиков
  • Добавление шаблонов

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

Дальше мы разберем весь процесс создания круда на примере каталога школ программирования за исключением работы с базой данных и тестов. Начнем с роутинга. Полный круд включает минимум семь маршрутов. Их может быть больше, так как любое из действий может повторяться не один раз:

МетодМаршрутШаблонОписание
GET/schoolsschools/index.htmlСписок школ
GET/schools/{id}schools/show.htmlИнформация о школе
GET/schools/newschools/new.htmlФорма создания новой школы
POST/schoolsСоздание новой школы
GET/schools/{id}/editschools/edit.htmlФорма редактирования школы
PATCH/PUT/schools/{id}Обновление школы
DELETE/schools/{id}Удаление школы

Такое соглашение изначально появилось в Rails и затем было адаптировано во многих фреймворках на языках отличных от Ruby.

В этом уроке мы разберем первые два маршрута: просмотр списка и конкретного ресурса. Остальные рассмотрим в следующих уроках.

Нейминг

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

В этом курсе мы будем придерживаться ресурсного наименования обработчиков. То есть название обработчика будет состоять из множественного имени сущности (users, courses) и действия (index, show, post).

К примеру, обработчик, выводящий список пользователей, будет users_index(), а выводящий конкретного пользователя - users_show().

Список (index)

Общий алгоритм вывода списка всегда проходит по одному сценарию и не зависит от языка программирования:

  1. Извлекаем список из базы данных. Обычно с учетом пейджинга
  2. Передаем данные в шаблон
  3. Выводим данные в шаблоне, используя цикл

image_processing.png

Обычно в этот список добавляют различные действия, которые можно выполнять над сущностями. Например, редактирование, удаление или просмотр.

Обработчик

@app.route("/schools")
def schools_index():
    repo = SchoolRepository()
    schools = repo.content()

    return render_template(
        "schools/index.html",
        schools=schools,
    )

Шаблон

<table>
    {% for school in schools %}
    <tr>
      <td>
          {{ school.id }}
      </td>
      <td>
          <a href="{{ url_for('schools_show', id=school.id) }}">{{ school.name }}</a>
      </td>
    </tr>
    {% endfor %}
</table>

Отображение (show)

Это страница, на которой описана конкретная сущность. Например, на Хекслете к таким страницам относятся: профиль пользователя, страница курса, страница профессии, страница урока. Как и в случае со списком, порядок действий для отображения всегда один и тот же:

  1. Из адреса извлекается идентификатор сущности
  2. Выполняется поиск сущности в хранилище
  3. Она передается в шаблон
  4. В шаблоне рисуется красивый вывод

Обработчик

@app.route("/schools/<id>")
def schools_show(id):
    repo = SchoolRepository()
    school = repo.find(id)

    return render_template(
        "schools/show.html",
        school=school,
    )

Шаблон

<div>
  {{ school.id }}: {{ school.name }}
</div>

Если сущность была удалена или ее вообще не существовало, то с точки зрения HTTP такой адрес сайта должен вернуть HTTP-код 404. Правильным способом будет использовать функцию abort - она сгенерирует указанную ошибку. Если в нашем приложении также есть обработчки ошибок, то он выведет шаблон на перехваченную ошибку:

@app.route("/schools/<id>")
def schools_show(id):
    repo = SchoolRepository()
    school = repo.find(id)

    if not school:
        abort(404)

    return render_template(
        "schools/show.html",
        school=school,
    )


@app.errorhandler(404)
def not_found(error):
    return "Oops!", 404

Заключение

Мы познакомились с CRUD-операциями, которые считаются типичными для веб-разработки: создание, чтение, обновление и удаление. Также мы подробно разобрали первые два маршрута: просмотр списка и конкретного ресурса. Далее рассмотрим остальные.

Рекомендуемые программы