[Express] CRUD 수정

2023. 7. 4. 16:14공부 중/Node.js

0. 참고자료

 

 

상세보기 페이지 구현 - 생활코딩

수업소개 상세보기 페이지를 Express 버전으로 변환해볼 것입니다. 이 과정에서 query string을 사용하지 않는 pretty url(clean url, semantic url..)로 라우트 기능을 구현하는 방법을 살펴보겠습니다.  강의

opentutorials.org

 


1. READ

 

 

READ 수정 · ramen4598/Study_nodeJS@9324ccb

ramen4598 committed Jul 3, 2023

github.com

 

  • app.get()을 사용하기.
  • 정적인 파일을 제공하기 위한 라우터 생성. (임시)
  • response.sendFile(path) : 이전과 달리 스스로 파일의 확장자를 인식해서 파일의 Content-type을 전달함.
  • Clean url로 변경.

 


2. CREATE

 

CREAT 수정 · ramen4598/Study_nodeJS@984fe03

ramen4598 committed Jul 3, 2023

github.com

 

 

  • response.redirect(`/page/${result.insertId}`);
    : express에서 redirect 하는 방법.
    : 상태 번호와 response.end()를 생략할 수 있어서 편하다.

3. UPDATE

 

https://github.com/ramen4598/Study_nodeJS/commit/be162a0e43ae8d47fdbd2bcead3b5cc0a1d5f5dd

 

UPDATE 수정 · ramen4598/Study_nodeJS@be162a0

ramen4598 committed Jul 3, 2023

github.com

 

 


4. DELETE

 

https://github.com/ramen4598/Study_nodeJS/commit/622ca028480c360894b7ef292251f6fb002ce1c9

 

DELET 수정 · ramen4598/Study_nodeJS@622ca02

ramen4598 committed Jul 3, 2023

github.com

 

 


5. 지금까지 코드

 

main.js

더보기
const qs = require("querystring");
const sanitizeHtml = require("sanitize-html");
const template = require("./template.js");
const db = require('./db.js');

/** new Ready(title, des, control, author)   
* @value : title, description, contol, author, html
* @method : makeHtml, response
*/
class Ready{
  constructor(title, des, control, author){
    this.title = title;
    this.description = des;
    this.control = control;
    this.author = author;
    this.html = '';
  }
  async makeHtml() {
    this.html = await template.HTML(this);
  }
  response(response){
    response.status(200).send(this.html);
  }
}

exports.home = function (request,response) {
    const title = "Welcome :)";
    const description = "Here is for to test node.js server :)";
    const control = `
      <input type="button" value="create" onclick="redirect(this, '')"/>
    `;
    const author = '';
    const undefinedCase = new Ready(title, description, control, author);
    undefinedCase.makeHtml()
    .then(()=>{undefinedCase.response(response)});
}

exports.page = function (request, response) {
  const pageId = request.params.pageId;
    db.query(
      `SELECT * FROM topic LEFT JOIN author ON topic.author_id= author.id WHERE topic.id=?`,
      [pageId],
      function (error, topic) {
        if (error) {
          throw error;
        }
        const title = topic[0].title;
        const description = topic[0].description;
        const control = `
        <input type="button" value="create" onclick="redirect(this, '')"/>
        <input type="button" value="update" onclick="redirect(this, '${pageId}')"/>
        <form id="frm" action="/delete_process" method="post" style="display:inline">
          <input type="hidden" name="id" value="${pageId}">
          <input type="button" value="delete" 
          onclick="if(confirm('really delete?')==true){document.getElementById('frm').submit();}">
        </form>
      `;
        const author = `${topic[0].name} 작성`;
        const definedCase = new Ready(title, description, control, author);
        definedCase.makeHtml()
        .then(()=>{definedCase.response(response)});
      }
    );
}

exports.create = async function (request, response) {
    let title = "create";
    let authorSelect = await template.authorSelect('');
    let description = `
        <form action="/create_process" method="post">
            <p>${authorSelect}</p>
            <p><input type="text" name="title" placeholder="title"></p>
            <p>
                <textarea name="description" placeholder="description"></textarea>
            </p>
            <p>
                <input type="submit">
            </p>
        </form>
      `;
    let control = '';
    let author  = '';
    const createCase = new Ready(title, description, control, author);
    createCase.makeHtml()
    .then(()=>{createCase.response(response)});
}

exports.create_process = function (request, response) {
    let body = "";
    request.on("data", function (data) {
      body += data;
    });
    request.on("end", function () {
      let post = qs.parse(body);
      let title = post.title;
      let description = post.description;
      let sanitizedTitle = sanitizeHtml(title);
      let sanitizedDesc = sanitizeHtml(description);
      db.query(
        `INSERT INTO topic (title, description, created, author_id) 
        VALUES (?, ?, NOW(), ?)`,
        [sanitizedTitle, sanitizedDesc, post.author],
        function (error, result) {
          if (error) {
            throw error;
          }
          response.redirect(`/page/${result.insertId}`);
        }
      );
    });
}

exports.update = async function (request, response) {
    const pageId = request.params.pageId;
    try{
        const promiseDB = db.promise();
        const [topic, fields] = await promiseDB.query(`SELECT * FROM topic WHERE id=?`,[pageId]);
        const authorSelect = await template.authorSelect(topic[0].author_id);
        const id = pageId;
        const title = topic[0].title;
        const description = `
          <form action="/update_process" method="post">
              <p>${authorSelect}</p>
              <p>
              <input type="hidden" name="id" value="${id}">
              <input type="text" name="title" placeholder="title" value="${title}"> </p>
              <p>
                   <textarea name="description" placeholder="description">${topic[0].description}</textarea>
              </p>
              <p>
                   <input type="submit">
              </p>
          </form>
        `;
        let control = ``;
        const author = ``;
        const updateCase = new Ready(title, description, control, author);
        updateCase.makeHtml()
        .then(()=>{updateCase.response(response)});
    }catch(error){
        throw error;
    }
}

exports.update_process = function (request, response) {
    let body = "";
    request.on("data", function (data) {
      body += data;
    });
    request.on("end", function () {
      let post = qs.parse(body);
      let id = post.id;
      let title = post.title;
      let description = post.description;
      let sanitizedTitle = sanitizeHtml(title);
      let sanitizedDesc = sanitizeHtml(description);
      db.query(
        `UPDATE topic 
          SET title=?, description=?, author_id=?
          WHERE id=?`,
        [sanitizedTitle, sanitizedDesc, post.author, id],
        function (error, result) {
          if (error) {
            throw error;
          }
          response.redirect(`/page/${id}`);
        }
      );
    });
}

exports.delete_process = function (request, response) {
    let body = "";
    request.on("data", function (data) {
      body += data;
    });
    request.on("end", function () {
      let post = qs.parse(body);
      let id = post.id;
      db.query(`DELETE FROM topic WHERE id=?`,[id],function (error) {
        if (error){
          throw error;
        }
        response.redirect('/');
      });
    });
}

 

topic.js

더보기
const qs = require("querystring");
const sanitizeHtml = require("sanitize-html");
const template = require("./template.js");
const db = require('./db.js');

/** new Ready(title, des, control, author)   
* @value : title, description, contol, author, html
* @method : makeHtml, response
*/
class Ready{
  constructor(title, des, control, author){
    this.title = title;
    this.description = des;
    this.control = control;
    this.author = author;
    this.html = '';
  }
  async makeHtml() {
    this.html = await template.HTML(this);
  }
  response(response){
    response.status(200).send(this.html);
  }
}

exports.home = function (request,response) {
    const title = "Welcome :)";
    const description = "Here is for to test node.js server :)";
    const control = `
      <input type="button" value="create" onclick="redirect(this, '')"/>
    `;
    const author = '';
    const undefinedCase = new Ready(title, description, control, author);
    undefinedCase.makeHtml()
    .then(()=>{undefinedCase.response(response)});
}

exports.page = function (request, response) {
  const pageId = request.params.pageId;
    db.query(
      `SELECT * FROM topic LEFT JOIN author ON topic.author_id= author.id WHERE topic.id=?`,
      [pageId],
      function (error, topic) {
        if (error) {
          throw error;
        }
        const title = topic[0].title;
        const description = topic[0].description;
        const control = `
        <input type="button" value="create" onclick="redirect(this, '')"/>
        <input type="button" value="update" onclick="redirect(this, '${pageId}')"/>
        <form id="frm" action="/delete_process" method="post" style="display:inline">
          <input type="hidden" name="id" value="${pageId}">
          <input type="button" value="delete" 
          onclick="if(confirm('really delete?')==true){document.getElementById('frm').submit();}">
        </form>
      `;
        const author = `${topic[0].name} 작성`;
        const definedCase = new Ready(title, description, control, author);
        definedCase.makeHtml()
        .then(()=>{definedCase.response(response)});
      }
    );
}

exports.create = async function (request, response) {
    let title = "create";
    let authorSelect = await template.authorSelect('');
    let description = `
        <form action="/create_process" method="post">
            <p>${authorSelect}</p>
            <p><input type="text" name="title" placeholder="title"></p>
            <p>
                <textarea name="description" placeholder="description"></textarea>
            </p>
            <p>
                <input type="submit">
            </p>
        </form>
      `;
    let control = '';
    let author  = '';
    const createCase = new Ready(title, description, control, author);
    createCase.makeHtml()
    .then(()=>{createCase.response(response)});
}

exports.create_process = function (request, response) {
    let body = "";
    request.on("data", function (data) {
      body += data;
    });
    request.on("end", function () {
      let post = qs.parse(body);
      let title = post.title;
      let description = post.description;
      let sanitizedTitle = sanitizeHtml(title);
      let sanitizedDesc = sanitizeHtml(description);
      db.query(
        `INSERT INTO topic (title, description, created, author_id) 
        VALUES (?, ?, NOW(), ?)`,
        [sanitizedTitle, sanitizedDesc, post.author],
        function (error, result) {
          if (error) {
            throw error;
          }
          response.redirect(`/page/${result.insertId}`);
        }
      );
    });
}

exports.update = async function (request, response) {
    const pageId = request.params.pageId;
    try{
        const promiseDB = db.promise();
        const [topic, fields] = await promiseDB.query(`SELECT * FROM topic WHERE id=?`,[pageId]);
        const authorSelect = await template.authorSelect(topic[0].author_id);
        const id = pageId;
        const title = topic[0].title;
        const description = `
          <form action="/update_process" method="post">
              <p>${authorSelect}</p>
              <p>
              <input type="hidden" name="id" value="${id}">
              <input type="text" name="title" placeholder="title" value="${title}"> </p>
              <p>
                   <textarea name="description" placeholder="description">${topic[0].description}</textarea>
              </p>
              <p>
                   <input type="submit">
              </p>
          </form>
        `;
        let control = ``;
        const author = ``;
        const updateCase = new Ready(title, description, control, author);
        updateCase.makeHtml()
        .then(()=>{updateCase.response(response)});
    }catch(error){
        throw error;
    }
}

exports.update_process = function (request, response) {
    let body = "";
    request.on("data", function (data) {
      body += data;
    });
    request.on("end", function () {
      let post = qs.parse(body);
      let id = post.id;
      let title = post.title;
      let description = post.description;
      let sanitizedTitle = sanitizeHtml(title);
      let sanitizedDesc = sanitizeHtml(description);
      db.query(
        `UPDATE topic 
          SET title=?, description=?, author_id=?
          WHERE id=?`,
        [sanitizedTitle, sanitizedDesc, post.author, id],
        function (error, result) {
          if (error) {
            throw error;
          }
          response.redirect(`/page/${id}`);
        }
      );
    });
}

exports.delete_process = function (request, response) {
    let body = "";
    request.on("data", function (data) {
      body += data;
    });
    request.on("end", function () {
      let post = qs.parse(body);
      let id = post.id;
      db.query(`DELETE FROM topic WHERE id=?`,[id],function (error) {
        if (error){
          throw error;
        }
        response.redirect('/');
      });
    });
}

 

template.js

더보기
const db = require('./db.js');

module.exports = {
  HTML: async function (Ready) {
    const list = await this.List();
    return `
     <!DOCTYPE html>
     <html lang="en">
       <head>
         <meta charset="UTF-8" />
         <meta http-equiv="X-UA-Compatible" content="IE=edge" />
         <meta name="viewport" content="width=device-width, initial-scale=1.0" />
         <title>WEB - ${Ready.title}</title>
         <link rel="stylesheet" href="/etc/style.css">
         <script src="/etc/lib/color.js"></script>
         <script src="/etc/lib/crudBtn.js"></script>
       </head>
       <body>
         <div id="top">
           <h1><a href="/">Board</a></h1>
           <input type="button" value="night" onclick="nightDayHandler(this)"/> </div>
         <div id="grid">
          ${list}
          <div id="article">
            <div id="control">${Ready.control}</div>
            <h2>${Ready.title}</h2>
            <p>
              ${Ready.author}
            </p>
            <p>
              ${Ready.description}
            </p>
          </div>
        </div>
       </body>
      </html>
    `;
  },
  List: async function () {
    try {
      const promiseDB = db.promise();
      const [topics, fields] = await promiseDB.query(`SELECT * FROM topic`);
      let list = "<ul>";
      topics.forEach(topic => {
        list += `<li><a href="/page/${topic.id}">${topic.title}</a></li>`;
      });
      list += "</ul>";
      return list;
    } catch (error) {
      throw error;
    }
  },authorSelect: async function(author_id){
    try {
      const promiseDB = db.promise();
      const [authors, fields] = await promiseDB.query(`SELECT * FROM author`);
      let tag = '';
      authors.forEach(author => {
        let selected ='';
        if (author.id === author_id){
          selected = 'selected';
        }
        tag += `<option value="${author.id}" ${selected}>${author.name}</option>`;
      });
      return `
        <select name="author">
          ${tag}
        </select>
      `
    }catch(error){
     throw error;
    }
  }
};

 

db.js

더보기
const mysql = require("mysql2");

const db = mysql.createConnection({
  host: process.env.MYSQL_HOST,
  user: process.env.MYSQL_USER,
  password: process.env.MYSQL_PASSWORD,
  database: process.env.MYSQL_DATABASE,
  port: process.env.MYSQL_PORT,
});
db.connect();
module.exports = db;

 

etc.js

더보기
const express = require('express');
const router = express.Router();
const main = require('../main.js');

router.get('/style.css', (request, response)=>{
    const path = `${main.mainPath}/style.css`;
    response.sendFile(path);
})
router.get('/lib/color.js', (request, response)=>{
    const path = `${main.mainPath}/lib/color.js`;
    response.sendFile(path);
})
router.get('/lib/crudBtn.js', (request, response)=>{
    const path = `${main.mainPath}/lib/crudBtn.js`;
    response.sendFile(path);
})
router.get('*', function(request, response) {
    response.status(404).send("Not found");
});

module.exports = router;

 


'공부 중 > Node.js' 카테고리의 다른 글

[Express] 미들웨어 작성  (0) 2023.07.05
[Express] 미들웨어 사용  (0) 2023.07.05
[Express] Routing  (0) 2023.07.04
[Express] 시작하기  (0) 2023.07.04
[Node.js] .env 파일 사용하기  (0) 2023.07.04