# 6.19- 22 Edit Video

이원규·2022년 6월 21일
0

Itube

목록 보기
21/46
post-custom-banner

1. Video Detail

1. video.pug에서 우리가 비디오 타이틀을 다음과 같이 링크 처리 해줬음.그런데 이 주소를, video Router가 어떻게 다뤄야할지 모름.(regular expression 수정)

-> 그 이유는 우리가 router에 추가할 수 있는 Regular Expression(정규표현식)때문에 생기는 것.
위에서는 (\d+)가 정규표현식. 이건 숫자만으로 된 id를 다루기엔 좋지만 mongoDB가 만든 id
형식과는 맞지 않음.

a(href=`/videos/${video.id}`)=video.title
videoRouter.get("/:id(\\d+)", watch);
videoRouter.route("/:id(\\d+)/edit").get(getEdit).post(postEdit);
// ex: http://localhost:4000/videos/62a6f150841eb28279d5c416
videoRouter.route("/upload").get(getUpload).post(postUpload);
  • 해결법 1: 비디오 라우터의 "/:id(\d+)"에서 "(\d+)"를 빼준다. 그런 뒤, upload라우터를
    맨 위로 배치시켜준다.(맨 위 배치시키는 이유: 안 그러면 upload를 id로 인식하기 때문)
videoRouter.route("/upload").get(getUpload).post(postUpload);
videoRouter.get("/:id", watch);
videoRouter.route("/:id/edit").get(getEdit).post(postEdit);
  • 해결법 2:
    이번 코딩에서는 이 방법을 이용함. 이 방법은 Documentation에 있는데, documentation에서 mongoDB id(ex:62a6f150841eb28279d5c416)를 조사해서 이걸로 regular expression을 만들어 볼 것임.regular expression 테스트 하기
    monoDB id 형식: Can be a 24 byte(24글자) hex string(16진수)임. mongoDB id 출처, Regular Expression MDN
    16진수: 0-9까지의 숫자와 A-F까지의 영어로 이루어진 것임.[0-9a-f]
videoRouter.get("/:id([0-9a-f]{24})", watch);//24글자의 16진수라는 뜻.
videoRouter.route("/:id([0-9a-f]{24})/edit").get(getEdit).post(postEdit);
videoRouter.route("/upload").get(getUpload).post(postUpload);

2. watch.pug & watch controller 수정(video.views를 안 보내주는데, 이게 pug에 있어서)

  • watch.pug
extends base.pug

block content 
    div
        p=video.description
        small=video.createdAt
    a(href=`${video.id}/edit`) Edit Video →
  • videoController(watch controller)
    -> model.findOne, model.findById 이용. MDN: mongoose queries
    1. model.findOne: 내가 보내는 모든 condition을 적용시켜줌. ex: 조회수 25인 영상 찾을 수 있게해줌.
    2. model.findById: id로 영상을 찾아낼 수 있는 기능을 지원해줌.
export const watch = async(req,res) => {
    const id = req.params.id;
    const video = await Video.findById(id);//Video에서 찾아도 되는 이유: 이 파일에 mongoose가 import돼 있으며, 이는  mongoDB와 이어져 있고 이를 이용해 Video model을 만들었으므로 자연스레 찾을 수 있게됨.
    return res.render("watch",{pageTitle : video.title, video});
}

2. Edit Video

Model MDN

2.1 들어가기 전 몇가지 수정하기

- findOne.exec()

  • .exec(): 이 부분이 query를 실행시키는 부분임. 쉽게 말해 mongoose는 내부적으로 만약 내가 .exec()를 호출하면 promise가 return될 것임. 하지만 promise에 대해서는 전혀 신경 안 써도 됨.
    예시:
await Adventure.findOne({ country: 'Croatia' }).exec();

- 만약 검색한 video가 없다면(null이면) 에러 처리해주기! 404 error가 뜨게할 것임.

  • videoController(watch controller)
export const watch = async(req,res) => {
    const id = req.params.id;
    const video = await Video.findById(id);//Video에서 찾아도 되는 이유: 이 파일에 mongoose가 import돼 있으며, 이는  mongoDB와 이어져 있고 이를 이용해 Video model을 만들었으므로 자연스레 찾을 수 있게됨.
    if(!video){
        return res.render("404", { pageTitle: "Video not found." });
    }
    return res.render("watch",{pageTitle : video.title, video});
}
  1. 1에서 에러처리에 404템플릿을 불렀으므로, 404템플릿 만들기.(views/404.pug)
  • 404.pug
extends base.pug

- base.pug로 돌아가서 모든 링크에 제대로 접근할 수 있도록 수정. -> Home으로 가는 링크 추가

  • base.pug
doctype html
html(lang="ko")
    head
        title #{pageTitle} | WeTube
        link(rel="stylesheet" href="https://unpkg.com/mvp.css")
    body 
        header
            h1=pageTitle
            nav 
                ul 
                    li 
                        a(href="/videos/upload") Upload Video
                    li 
                        a(href="/") Home
        main 
            block content
            include partials/footer.pug

2.2 Edit Video

2.2.1 Edit video controller & edit.pug 완성하기

  • edit.pug
  1. description, hashtags input도 넣어줌
    -> 이 때, hashtags의 value가 array형태 그대로 나와서 format을 해줄 것임. .join()을 이용.
extends base.pug

block content 
    h4 Update Video
    form(method="POST")
        input(name="title", placeholder="Video Title", value=video.title,required)
        input(name="description",placeholder="Description", required, type="text", minlength=20, value=video.description)
        input(name="hashtags",placeholder="Hashtags, separated by comma.", required, type="text", value=video.hashtags.join())
        input(type="submit",value="save")
  • get Edit
export const getEdit = async(req,res) => {
    const id = req.params.id;
    const video = await Video.findById(id);
    if(!video){
        return res.render("404", { pageTitle: "Video not found." });
    }
    return res.render("edit",{pageTitle:`Editing ${video.title}`, video});
}

2.2.2 영상의 변경내용을 실제로 update하기.

findByIdAndUpdate(id, {변경 내용}) / or findOneAndUpdate()

-> id로 비디오를 찾고, 변경내용을 update해줌.
findByIdAndUpdate MDN
findOneAndUpdate MDN

model.exists({property})

-> 원하는 모델의 propery를 적어 넣으면 그것에 따라 DB에서 필터링해서 원하는 게 존재하는지 알아낼 수 있음. return 값은 boolean(true/false)임
-> getEdit처럼 화면에 나타나야할 경우엔 findById가 적합하지만, 굳이 video객체를 템플릿에 보이거나 가져올 필요가 없는 경우엔 exists가 더 적합하다.
Model.exists MDN

update코드

  • video controller (-> post controller)
//별로 좋지 않은 코드로 작성
export const postEdit = async (req, res) => {//post를 하면 mongoDB 내의 값을 변경해줌.
    const {id} = req.params;
    const {title, description, hashtags } = req.body;
    const video = await Video.findById(id);
    if(!video){
        return res.render("404", { pageTitle: "Video not found." });
    }
    video.title = title;
    video.description = description;
    video.hashtags = hashtags.split(",").map((word) => word.startsWith("#") ? word :`#${word}`);//startsWith(word): word로 시작한다면 이란 뜻인듯. 
    await video.save();//post로 바꾼 mongoDB내의 변경 내용을 저장함. <- 이게 없으면 저장이 안됨.
    return res.redirect(`/videos/${id}`);
}

// 그나마 좋은 코드 !!!!!!!!!!!!!!!!!!!! 
export const postEdit = async (req, res) => {//post를 하면 mongoDB 내의 값을 변경해줌.
    const {id} = req.params;
    const {title, description, hashtags } = req.body;
    const video = await Video.exists({_id:id});//video: DB에서 검색한 영상 object , Video: 우리가 만든 비디오 모델임.
    if(!video){
        return res.render("404", { pageTitle: "Video not found." });
    }
    await Video.findByIdAndUpdate(id, {
        title:title,
        description:description,
        hashtags:hashtags.split(",").map((word) => word.startsWith("#") ? word :`#${word}`),
    })
    return res.redirect(`/videos/${id}`);
}
profile
github: https://github.com/WKlee0607
post-custom-banner

0개의 댓글