В этой статье мы рассмотрим, как создать роуты для выполнения операций CRUD (Create, Read, Update, Delete) в Express.js для таблицы «Задачи» в приложении Todolist. Express.js — это популярный фреймворк для создания веб-приложений на Node.js, и он идеально подходит для создания бэкенда для Todolist.
Начнем с основ
Прежде чем мы начнем создавать роуты, убедитесь, что вы установили и настроили Express.js и подключили базу данных PostgreSQL. Мы будем считать, что у вас уже есть настроенный сервер Express и соединение с базой данных.
Если вы еще этого не сделали — вот статьи:
Например:
- Create (Создание): Используйте HTTP POST для отправки данных на сервер и создания новых ресурсов.
- Read (Чтение): HTTP GET прекрасно подходит для получения данных с сервера без изменения его состояния.
- Update (Обновление): Для изменения существующих ресурсов, используйте HTTP PUT или PATCH, в зависимости от того, полностью ли вы заменяете ресурс или обновляете часть его данных.
- Delete (Удаление): Используйте HTTP DELETE для удаления ресурсов с сервера, что делает ваше взаимодействие с сервером более согласованным и безопасным.
Подготовка к работе
Прежде чем мы начнем создавать роуты, давайте настроим подключение к базе данных PostgreSQL и определим SQL-запросы для каждой из операций CRUD. Это позволит нам организовать код более структурированно.
Более подробно SQL-запросы для Todolist обсуждали в статье: Основы PostgreSQL, базовые операции, таблицы и схемы (ссылка).
Создание сервера и подключение к базе данных.
const express = require("express");
const app = express();
const { Pool } = require("pg");
// Запуск сервера
const PORT = 4000;
app.listen(PORT, () => {
console.log(`Сервер запущен на порту ${PORT}`);
});
// Конфигурация базы данных PostgreSQL
const pool = new Pool({
user: 'postgres', // Пользователь базы данных
host: 'localhost', // Хост базы данных (обычно localhost)
database: 'myexpressdb', // Название базы данных, которую мы создали
password: 'your-postgres-password', // Пароль пользователя postgres
port: 5432, // Порт PostgreSQL (по умолчанию 5432)
});
Переменные для создания и удаления таблицы
// SQL-запрос на создание таблицы задач
const createTasksTableQuery = `
CREATE TABLE IF NOT EXISTS tasks (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT,
due_date DATE,
completed BOOLEAN
)
`;
// SQL-запрос на удаление таблицы задач
const deleteTasksTableQuery = `
DROP TABLE IF EXISTS tasks
`;
Переменные для CRUD запросов
// SQL-запрос для создания задачи
const createTaskQuery = `
INSERT INTO tasks (title, description, due_date, completed)
VALUES ($1, $2, $3, $4)
RETURNING *
`;
// SQL-запрос для получения всех задач
const getAllTasksQuery = `
SELECT * FROM tasks
`;
// SQL-запрос для получения задачи по ID.
const getTaskByIdQuery = `
SELECT * FROM tasks
WHERE id = $1
`;
// SQL-запрос для обновления задачи
const updateTaskQuery = `
UPDATE tasks
SET title = $1, description = $2, due_date = $3, completed = $4
WHERE id = $5
RETURNING *
`;
// SQL-запрос для удаления задачи
const deleteTaskQuery = `
DELETE FROM tasks
WHERE id = $1
RETURNING *
`;
Роуты для работы с таблицей задач
Создание таблицы tasks
// Роут для создания таблицы tasks (если её ещё не существует)
app.post('/create-tasks-table', async (req, res) => {
try {
// Выполняем SQL-запрос на создание таблицы
await pool.query(createTasksTableQuery);
res.json({ message: 'Таблица tasks успешно создана' });
} catch (error) {
console.error('Ошибка при создании таблицы tasks:', error);
res.status(500).json({ error: 'Не удалось создать таблицу tasks' });
}
});
Удаление таблицы tasks
// Роут для удаления таблицы tasks (если она существует)
app.delete('/delete-tasks-table', async (req, res) => {
try {
// Выполняем SQL-запрос на удаление таблицы
await pool.query(deleteTasksTableQuery);
res.json({ message: 'Таблица tasks успешно удалена' });
} catch (error) {
console.error('Ошибка при удалении таблицы tasks:', error);
res.status(500).json({ error: 'Не удалось удалить таблицу tasks' });
}
});
Создание задачи (Create)
Давайте создадим роут для добавления новой задачи в Todolist. Мы будем принимать данные о задаче в формате JSON.
Первый роут подробно закомментируем — остальные создаются по аналогии.
// Роут для создания новой задачи в Todolist
app.post('/tasks', async (req, res) => {
try {
// Извлекаем данные о задаче из запроса
const { title, description, due_date, completed } = req.body;
// Создаем массив значений для SQL-запроса
const values = [title, description, due_date, completed];
// Выполняем SQL-запрос для создания задачи
const result = await pool.query(createTaskQuery, values);
// Отправляем созданную задачу в формате JSON в ответе
res.json(result.rows[0]);
} catch (error) {
console.error('Ошибка при создании задачи:', error);
// В случае ошибки отправляем статус 500 и сообщение об ошибке
res.status(500).json({ error: 'Не удалось создать задачу' });
}
});
Получение всех задач (Read)
Создадим роут для получения списка всех задач в Todolist.
app.get('/tasks', async (req, res) => {
try {
const result = await pool.query(getAllTasksQuery);
res.json(result.rows);
} catch (error) {
console.error('Ошибка при получении списка задач:', error);
res.status(500).json({ error: 'Не удалось получить список задач' });
}
});
Получение задачи по ID (Read)
Давайте добавим возможность получения конкретной задачи по её идентификатору.
app.get('/tasks/:id', async (req, res) => {
try {
const taskId = req.params.id;
const result = await pool.query(getTaskByIdQuery, [taskId]);
if (result.rows.length === 0) {
res.status(404).json({ error: 'Задача не найдена' });
} else {
res.json(result.rows[0]);
}
} catch (error) {
console.error('Ошибка при получении задачи:', error);
res.status(500).json({ error: 'Не удалось получить задачу' });
}
});
Обновление задачи (Update)
Добавим роут для обновления информации о задаче. Мы будем передавать новые данные в формате JSON.
app.put('/tasks/:id', async (req, res) => {
try {
const taskId = req.params.id;
const { title, description, due_date, completed } = req.body;
const values = [title, description, due_date, completed, taskId];
const result = await pool.query(updateTaskQuery, values);
if (result.rows.length === 0) {
res.status(404).json({ error: 'Задача не найдена' });
} else {
res.json(result.rows[0]);
}
} catch (error) {
console.error('Ошибка при обновлении задачи:', error);
res.status(500).json({ error: 'Не удалось обновить задачу' });
}
});
Удаление задачи (Delete)
И, наконец, создадим роут для удаления задачи по её идентификатору.
app.delete('/tasks/:id', async (req, res) => {
try {
const taskId = req.params.id;
const result = await pool.query(deleteTaskQuery, [taskId]);
if (result.rows.length === 0) {
res.status(404).json({ error: 'Задача не найдена' });
} else {
res.json({ message: 'Задача успешно удалена' });
}
} catch (error) {
console.error('Ошибка при удалении задачи:', error);
res.status(500).json({ error: 'Не удалось удалить задачу' });
}
});