728x90

https://velog.io/@pkbird/Nunjucks-basic

 

팔로우하기

팔로우끊기

 

버튼교체!!!!

 

해결함 

넌적스 제대로 안됐던 이유는 club.html코드보면서 라우터 mypage.js 걸로 왜 안되냐 하고 있었던 것~~

 

 (mypage에서 팔로우 정보 불러올때 썼던 것처럼)

 

club.html에서 쓸

followerIdList를 club.js에서 쓸거라고 넣어줘야 됐음

 


목표:

(나자신)   - 아무것도 안뜨게

(팔로잉한 사람followerIdlist에 포함되어있음)  - 팔로우끊기

(팔로우 안함사람) – 팔로우하기

 

///넌적스 if절은//

만약에 트윗유저가 followerIdlist에 포함되어있지 않고 나자신이 아니면

팔로우하기

그게 아니면(트윗유저가 followerIdlist에 포함되어있으면 그리고 나자신 아니면)

팔로우끊기

 


 

 

 

 

(좋아요는 아직 기능안해서 주석처리)

 

club.html

{% extends "layout.html" %} {% block css %}
<link rel="stylesheet" href="/club/stylesheets/club.css" />
{% endblock %} {% block content %}
<div class="search_field">
  <div class="fake_field">
    <input
      class="picture-search"
      type="text"
      name="search"
      placeholder="사진 검색"
    />
    <button class="picture-btn btn">검색</button>
  </div>
</div>

<div class="feed-container">
  <h3>인기 피드</h3>

  <!-- <form id="myFeed">
    <button id="feed-btn" type="submit" class="black btn">
      <a class="picture-uploads" href="/clubupload">업로드</a>
    </button>
    {% for twit in twits %}
    <tr class="clubMain">
      <td>
        <a href="/">
          <img style="width: 100px" src="{{twit.img}}" alt="섬네일"/>
        </a>
      </td>
    </tr>
    {% endfor %}
  </form> -->
  {% if user and user.id %}
  <button id="feed-btn" type="submit" class="black btn">
    <a class="picture-uploads" href="/clubupload">업로드</a>
  </button>
  {% endif %} {% for twit in twits %}
  <div class="twit">
    <input type="hidden" value="{{twit.User.id}}" class="twit-user-id" />
    <input type="hidden" value="{{twit.id}}" class="twit-id" />
    <div class="twit-author">{{twit.User.nick}}</div>

    {% if not followerIdList.includes(twit.User.id) and twit.User.id !== user.id
    %}
    <button class="twit-follow btn">팔로우하기</button>
    {% elif twit.User.id !== user.id%}
    <button class="twit-unfollow btn">팔로우끊기</button>
    {% endif %}

    <div class="twit-img">
      <a href="/clubdetail/:id"
        ><img style="width: 100px" src="{{twit.img}}" alt="섬네일"
      /></a>
    </div>

    <button class="like btn">좋아요</button>

    <button class="unlike btn">좋아요 취소</button>

    <div class="twit-content"></div>
  </div>
  {% endfor %}
</div>
{% endblock %} {% block script %}
<script>
  //팔로우
  document.querySelectorAll(".twit-follow").forEach(function (tag) {
    console.log("팔로이있는창");
    tag.addEventListener("click", function () {
      console.log("팔로우클릭");
      const myId = document.querySelector("#my-id");
      if (myId) {
        console.log("myid가져와지니?");
        const userId = tag.parentNode.querySelector(".twit-user-id").value;
        console.log(userId);
        //if (userId !== myId.value)원래 이거였음 근데 바꿔도 콘솔에는 찍히네

        if (userId !== myId.value) {
          if (confirm("팔로잉하시겠습니까?")) {
            console.log("팔로요청되나?");
            axios
              .post(`/user/${userId}/follow`)
              .then(() => {
                console.log("팔로됐나");
                location.reload();
              })
              .catch((err) => {
                console.log("에러");
                console.error(nperr);
              });
          }
        }
      }
    });
  });
  //팔로우끊기
  document.querySelectorAll(".twit-unfollow").forEach(function (tag) {
    tag.addEventListener("click", function () {
      const myId = document.querySelector("#my-id");
      console.log(myId);
      if (myId) {
        const userId = tag.parentNode.querySelector(".twit-user-id").value;

        if (userId !== myId.value) {
          if (confirm("팔로잉끊으시겠습니까?")) {
            console.log("팔로요청되나?");
            axios
              .post(`/user/${userId}/unfollow`)
              .then(() => {
                console.log("팔로됐나");
                location.reload();
              })
              .catch((err) => {
                console.log("에러");
                console.error(err);
              });
          }
        }
      }
    });
  });

  //   forEach.call(document.querySelectorAll(".like"), function (tag) {
  //   tag.addEventListener("click", function () {
  //     var isLoggedIn = document.querySelector("#my-id");
  //     var twitId = tag.parentNode.querySelector("#twit-id").value;
  //     if (idLoggedIn) {
  //       var xhr = new XMLHttpRequest();
  //       xhr.onload = function () {
  //         if (xhr.status === 200) {
  //           location.reload();
  //         } else {
  //           console.error(xhr.responseText);
  //         }
  //       };
  //       xhr.open("POST", "/club/" + twitId + "/like");
  //       xhr.send();
  //     }
  //   });
  // });
  // forEach.call(document.querySelectorAll(".unlike"), function (tag) {
  //   tag.addEventListener("click", function () {
  //     var isLoggedIn = document.querySelector("#my-id");
  //     var twitId = tag.parentNode.querySelector("#twit-id").value;
  //     if (idLoggedIn) {
  //       var xhr = new XMLHttpRequest();
  //       xhr.onload = function () {
  //         if (xhr.status === 200) {
  //           location.reload();
  //         } else {
  //           console.error(xhr.responseText);
  //         }
  //       };
  //       xhr.open("DELETE", "/club/" + twitId + "/like");
  //       xhr.send();
  //     }
  //   });
  // });
</script>

{% endblock %}

 location.reload(); //이거 새로고침!

<button class="twit-unfollow btn">팔로우끊기</button//띄어쓰기하면 클래스 하나 더 들어가는거

 

 

팔로잉한 데이터 가져오려면

라우터에서 만들어줘야했음!

 

 

경로는 라우터에서

get으로 club.html불러주고

use로 사용하겠다.

어떻게 사용할지~

 

club.js

const express = require("express");
const { isLoggedIn, isNotLoggedIn } = require("../middlewares");
const { Club, User } = require("../../models");
const router = express.Router();

router.use((req, res, next) => {
  res.locals.user = req.user;
  // res.locals.followerCount = 0;
  // res.locals.followingCount = 0;
  // res.locals.followerIdList = [];
  res.locals.followerCount = req.user ? req.user.Followers.length : 0;
  res.locals.followingCount = req.user ? req.user.Followings.length : 0;
  res.locals.followerIdList = req.user
    ? req.user.Followings.map((f) => f.id)
    : [];
  next();
});


router.get("/", async (req, res, next) => {
  try {
    const clubs = await Club.findAll({
      include: {
        model: User,
        attribute: ["id", "nick"],
      },
      order: [["createdAt", "DESC"]],
    });
    res.render("club/club", {
      title: "mountain feed",
      twits: clubs,
    });
  } catch (error) {
    console.error(error);
    next(error);
  }
});

module.exports = router;

참고로 라우트 쓸려면

 

app.js

에 라우트 선언해야함

const clubRouter = require("./routes/club/club");

미들웨어도 추가

app.use("/club"clubRouter);

 

 

 

 

결과물~!!

마이페이지~

 

 

 

 

 

https://design-system.service.gov.uk/components/tabs/

 

Tabs – GOV.UK Design System

Components Tabs Experimental This component is currently experimental because more research is needed to validate it. The tabs component lets users navigate between related sections of content, displaying one section at a time. Contents Past day Past week

design-system.service.gov.uk

이건 넌적스 유용하게 쓸 수 있을 거 같은 사이트

728x90
728x90

몽고디비

몽구스

스키마

 

몽구스 프로미스......를 지원한다는데 프로미스가 뭐여. 아 promise

https://www.zerocho.com/category/MongoDB/post/59b6228e92f5830019d41ac4

 

(MongoDB) Mongoose(몽구스) 프로미스

안녕하세요. 이번 시간에는 몽구스로 프로미스(promise)를 사용하는 방법에 대해 알아보겠습니다. 기본적으로 몽고DB(노드용 드라이버)는 콜백으로 결과값을 반환합니다. 콜백은 간단하지만, 다들

www.zerocho.com

CRUD는 대부분의 컴퓨터 소프트웨어가 가지는 기본적인 데이터 처리 기능인 Create(생성), Read(읽기), Update(갱신), Delete(삭제)를 묶어서 일컫는 말

 

 

 

비동기 콜백함수 프로미스 async/await 등 개념 설명 짱임

https://joshua1988.github.io/web-development/javascript/promise-for-beginners/

 

자바스크립트 Promise 쉽게 이해하기

(중급) 자바스크립트 입문자를 위한 Promise 설명. 쉽게 알아보는 자바스크립트 Promise 개념, 사용법, 예제 코드. 예제로 알아보는 then(), catch() 활용법

joshua1988.github.io

 

728x90
728x90

깔고 

 

콘솔에서 

cd "경로"

cd 경로 로 해도 되더라

 

 

!!!

C:\data\db

폴더 없으면 실행안돼! 반드시 폴더 먼저 만들어야함

 

 

mongod

 

기본적으로 27017번 포트에서 실행됨

 

몽고디비 사용할때마다 mongod 명령어로 먼저 서버를 실행해야 함

 

(매번 실행하기 귀찮으면 명령 프롬프트를 관리자 권한으로 실행한 뒤 명령어 입력하는 방법도 있음 책353쪽 참고.)

 

 

몽고디비 프롬프트 접속하려면 같은 폴더에서 콘솔 하나 더 열어 mongo 명령어 입력

mongo

 

 

프롬프트가 >로 바뀌면 성공

지금은 누구나 몽고디비에 접속할 수 있으니 

관리자 계정을 추가하자

 

> use admin
switched to db admin
> db.createUser({user:'이름',pwd:'비밀번호',roles:['root']})  나 오타진짜 많이 낸다...안돼서 꽤 찾음
Successfully added user: { "user" : "이름", "roles" : [ "root" ] }

 

db.createUser 메서드로 계정 생성!

user에 사용자 이름 넣고 pwd 자리에 사용할 비번 입력 roles로는 현재 모든 권한이 있는root를 부여

 

아까 mongod를 입력했던 콘솔을 종료한 뒤

이번에는 mongod --auth명령어로 접속 (--auth는 로그인이 필요하다는 뜻)

 

 

 

다른창 끄고

여기서도 

exit

로 나와주고

 

mongod --auth 명령어로 접속 --auth는 로그인이 필요하다는 뜻

 

 

접속할 때 

앞으로 

cd 경로

 

admin -u 이름 -p 비번

하고

 

콘솔에 데이터베이스 만들거면  use 데이터베이스명

데이터베이스목록을 확인하는 명령어 show dbs

 

 

 

 

 

 

 

728x90
728x90

https://ko.javascript.info/debugging-chrome

 

Chrome으로 디버깅하기

 

ko.javascript.info

https://jybaek.tistory.com/717

 

노드를 더 우아하게. npm 이야기

노드를 더 우아하게 해주는 주변 프로그램인 npm 을 이해하도록 해보자. npm 은 Node.js Package Manager 로 단어 그대로 패키지 관리를 돕는다. 언뜻보면 python 의 pip 와 그 형상이 비슷해보이기

jybaek.tistory.com

https://p-iknow.netlify.app/node-js/path-moudle/

 

Nodejs, path module, __dirname, __filename 에 대해 톺아보기 - p-iknow's devlog

웹펙을 입문하려 할 때 처음 마주하게 되는게 entry 옵션이고, entry 옵션을 설정할 때 path.resolve("...") 처럼, node.js 의 path 모듈이 쓰이는 것을 볼 수 있다. 나를 포함한 입문자들이 대충 경로를 설정

p-iknow.netlify.app

 

728x90
728x90

설치 완료 후

 

 

mysql로 접속

 

설치된 폴더 경로로 들어가서 

cd 폴더경로

 

 

들어가서> mysql -u root -p

 

비번 입력하면 뜸!

 

나가고 싶으면

exit

 

데이터베이스 생성

create database movie_db default character set utf8;

 

영화정보 넣을거라서  movie_db로 넣었음

 

create database movie_db default character set utf8;

(MySQL이 기본적으로 알고 있는 구문을 예약어라고 부름 예약어는 소문자로 써도 되지만 대문자로 쓰는게 좋아

사용자가 직접만든 이름이랑 구분하기 위해서)

 

 

이거 사용할거야~

mysql> USE movie_db;

 

 

이전에 만든

데이트베이스 리스트 보고 싶으면

mysql> show databases;

 

그중에서 사용할 꺼 USE 데이터베이스

하고 

테이블 보기

mysql> show tables;

 

 

 

 

 

 



 

 

 

테이블(데이터가 들어갈 수 있는 틀) 생성하는 명령어

 

create table [데이터베이스명. 테이블명] 

 

mysql>  CREATE TABLE products(
    -> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY);

 

 

아까 USE 테이터베이스명 해서 

생략해도 됨

 

 

만들어진 테이블 확인하는 명령어 

DESC 테이블명

 

 

 

테이블  컬럼 추가

ALTER TABLE `테이블명` ADD `컬럼명` VARCHAR(50) NOT NULL;

 

mysql> ALTER TABLE `products` ADD `name` VARCHAR(50) NOT NULL;

 

악 에러 뜬 이유가 `` 뱁틱이어서 그랬음..ㅎㅎ

 

 

이렇게 괄호로 묶어서 한번에 여러 개 넣어줄 수도 있음

 

 

 

 

개념 정리하고 가자~~~

 

(아직 데이터를 안넣어서 책에 나온 예시로 정리)

 

컬럼과 로우

id  name  age married
1 zero 24 false
2 nero 32 true
3 hero 28 false

 

컬럼(column) : id, name, age,married 과 같은 세로줄 

(age 컬럼에는 24,32,28과 같은 정보 담겨있음)

로우(row) : 1,zero,24,false와 같은 가로줄. 

 

필드 : 컬럼과 로우가 교차하는 칸 하나

컬럼은 세로필드의 집합

로우는 가로 필드의 집합

테이블에 데이터를 넣을 때는 미리 컬럼을 정의해두고 컬럼에 맞춰 데이터를 넣으면 된다.

 

컬럼의 자료형

  • INT : 정수 의미. 소수까지 저장하고 싶다면 FLOAT 나 DOUBLE 자료형 사용
  • VARCHAR(자릿수) : 가변길이. 0~자릿수인 문자열 넣을 수 있음
  • CHAR(자릿수) : 고정길이 자료형. 부족한 자릿수만큼 스페이스가 채워짐
  • TEXT : 긴 글 저장할 때 사용. 수백 자 이내의 문자열은 보통 VARCHAR(자릿수)사용하고 그보다 길면 TEXT 사용
  • TINYINT : -128부터 127까지의 정수 저장할 때 사용. 1또는 0만 저장하면 불값(Boolean)과 같은 역할 할 수 있음
  • DATETIME : 날짜와 시간에 대한 정보 담고 있음. 날짜 정보만 담는 DATE / 시간정보 담는 TIME 자료형

 

(자료형 뒤) 옵션

  • NULL 과  NOT NULL  : 빈칸 허용할지 여부 묻는 옵션
  • AUTO_INCREMENT : 숫자를 저절로 올리겠다는 뜻 (데이터 넣으면 알아서 id로 1번부여, 다음 2번 부여 이렇게)
  • UNSIGNED : 숫자 자료형에 적용되는 옵션. 음수 무시되고 0~4294967295까지 저장가능.나이 컬럼에 체크해두는게 좋음
  • ZEROFILL : 숫자의 자릿수가 고정되어 있을 때 사용할 수 있음(예) INT(4)인데 숫자1넣으면 0001이 되는 식)
  • created_at 에는 DEFAULT now()라는 옵션 붙어있음. 현재 시각 넣으라는 뜻. now()대신 CURRENT_TIMESTAMP를 적어도 같은 뜻이 됨. 사용자 정보를 넣으면 created_at 컬럼에는 넣는 순간의 시각이 자동으로 기록됨.
  • 해당 컬럼이 기본 키인 경우에 PRIMARY KEY옵션을 설정. 기본 키란 로우를 대표하는 고유한 값을 의미

 

DEFAULT CHARACTER SET 을 utf8로 설정하지 않으면 한글이 입력되지 않으니 반드시 설정해야 함

 

 

 

테이블 잘못 만들었을 경우 제거하는 법

DROP TABLE [테이블명] ;

 

데이터 입력

INSERT INTO 테이블명 (필드,필드) VALUE ('테이터','데이터'..)

 

선택

Select * from products

전체 선택

 

select 필드, 필드 from 테이블 where 조건

(조건검사 : where 데이터 베이스 안에서 원하는 데이터를 조건에 맞게)

 

 

 

 

 

 

 

 

기본적인 mySQL 관계(비교)연산자 : 주어진 좌우 값을 비교하는 연산자
좌변과 우변이 같다
!= 또는 <>     좌변과 우변이 다르다
<   작다
<=   작거나 같다
크다
>= 크거나 같다

 

 

 

예시

 

 

논리연산자 : 참(true), 거짓(false) 두 가지를 가지고 비교하는 연산자
AND , && 비교하는 값 모두 참(true)여야 결과가 참(true)
OR , ||  비교하는 값 중 하나라도 참(true)이면 결과가 (true) 

예시

 

 

만약 글자에서 특정 부분 일치하는 데이터를 조회하고 싶다면!

LIKE

%는 다른 경우 들어갈 자리에 붙여줌

 

 

정렬하기 

order by

전체 선택해서 

openDate 기준으로 오름차순

 

오름차순 asc (안적어도 자동이긴 함)

내림차순 desc

 

 

특정 위치에 있는 데이터를 선택

LIMIT

상위부터 2까지

 

 

 

 

 

데이터를 3개를 건너뛴 다음에 데이터 1개

 

 

명령어 순서 지켜야함!

 

 

데이터를 수정할 때

update라는 명령어 써주면 됨

여러개 수정할 때

콤마, 사용

 

 

데이터 삭제

테이블 삭제 

DROP TABLE 테이블명;

데이터베이스 삭제

DROP TABLE 데이터베이스 이름;

728x90
728x90

앞에 올린 글

노드js express로 로그인 창만들때 

헷갈렸던 거

 

 

app.get   app.post 차이

 

 

그니까(내가 본 설명글 / 이것도 있음)

get은 /주소 보이는 방식이라서 /뒤에 주소 써주는데로 이동하고 띄우고 get써서 경로이동할 수 있게 하고
post는 주소 안보여주는 방식. 눈에 보이지 않는 주소요청 받아처리함. post에서는 서버에서 처리할 일 요청할 수도 있고 데이터를 전송할 수도 있음

 

앞에 쓴 글

코드 보면

html에서

post 로 form 써서 

메인페이지랑

로그인페이지 둘다 name 데이터 전송해서 썼어

 

app.js 에서는 경로 이동 쉽게 할려고 get쓰고

post로 정보 받아서 썼구나

오호...

 

res.send 특징 

res.write 써야돼? 여러개 쓰고 싶으면?

 

https://fierycoding.tistory.com/18

 

  • res.send(body), res.send(status, body) : 클라이언트에 응답을 보냄. 상태 코드는 옵션. 기본 콘텐츠 타입은 text/html이므로 text/plain을 보내려면 res.set(‘Content-Type’, ‘text/plain’)을 먼저 호출 해야한다. JSON을 보낼거면 res.json을 쓰자.

여기 req res 메서드 개념 잘 정리 되어있다!!

 

사실 정말 가려운 곳 못긁었는데 차차 해보면서 알아가도록 ..

 

 

키 값

name vaule 차이가 뭐야

넘길 때 왜 name 넘겨주면 value는 왜 쓰지..  

 

 

 

 

Value = The value attribute specifies the value of an element.

Name = name is only to post form data. The name definies what the name of the attribute will be as soon as the form is submitted. So if you want to read this attribute later you will find it under the "name" in the POST or GET Request. Whereas the id is used to adress a field or element in javascript or css.

 설명굿

 

아하!!

맞다

 

이분 오타내심 value

요거네 name이 전달되고 value는 입력 태그의 초기값

 

HTML - input태그와 그 속성 type, value, name - 입력태그 (1)

HTML - input태그와 그 속성 type, value, name 입력태그 (1)  오늘은 input태그와 그 속성 type, value, name에 대해서 알아 보도록 하겠습니다. 태그 기초부터 알아보기 전에 압타나 스튜디오를 직접 설치 하.

yangbari.tistory.com

오호라 헷갈렸어

728x90

+ Recent posts