1. 로컬환경, 서버환경의 분리

 지난 글에서 AWS 라이트세일을 사용하여 pybo 서버를 오픈하기 위해 config/settings.py 의 ALLOWED_HOSTS 를

수정하였다. 그런데 이렇게 하면 로컬 개발환경에서 서버를 구동할 수 없는 문제가 발생한다. 그리고 ALLOWED_HOSTS

외에도 로컬 개발환경과 서버환경에서의 설정이 달라야하는 부분도 분명 존재할 것이다.  이런 문제를 해결하려면 

로컬환경과 서버환경에서의 설정을 달리 적용시킬 수 있어야한다.

 

 

2. settings.py 분리

 settings.py 를 분리하는 작업은 views.py 의 분리작업과 유사하게 진행된다. 

 

먼저 config 디렉토리에 settings 디렉토리를 생성한 뒤 기존 settings.py 를 base.py 로 파일명을 변경하여 settings

디렉토리로 옮긴다.  그 후 파일이 한층 더 디렉토리 내부로 이동했으니 BASE_DIR 끝에 .parent를 한번 더 붙여준다.

 

로컬 환경용 설정파일 local.py 를 생성하여 base.py 를 import 해주고 ALLOWED_HOSTS 를 빈 리스트로 설정한다.

 

서버 환경용 설정파일 prod.py 를 생성하여 base.py 를 import 해주고 ALLOWED_HOSTS 에 AWS 라이트세일

인스턴스의 고정 IP를 넣어준다.

 

이제 로컬측에서 python manage.py runserver --setings=config.settings.local 을 실행하면 서버가 정상적으로

구동되는 것을 확인할 수 있다.  --settings 는 어느파일을 settings.py 로 인식할지 지정하는 옵션이다.

 

 

3. alisas 를 사용한 서버 설정 자동화

sh 파일을 사용한 자동화는 sh 파일의 경로를 찾아가 실행해야하는 불편함이 있다.  이를 보다 편하게 바꿔보자.

 

cd ~
vi .bashrc

 

위와 같이 홈 디렉토리로 이동(cd ~)한 뒤 .bashrc 파일을 vi 로 열어 맨 아랫줄에 mysite 라는 alias 를 추가해준다.

DJANGO_SETTINGS_MODULE 는 서버 실행시 --settings=config.settings.local 옵션을 대신해주는 환경변수이다.

mysite='<실행할 명령어>' 에서 = 좌우로 띄어쓰기를 넣지 않도록 해야한다. 

 

.bashrc 파일을 저장한 뒤 실행시키는 것으로 수정사항을 반영해주고나서 alias 명령어를 실행시키면 mysite 가 alias

목록에 추가된 것을 확인할 수 있다. 

 

이제 어디서든 mysite 명령어로 서버 환경에서의 설정파일을 지정하고 프로젝트 디렉토리로 이동하여 가상환경에

진입하는 작업을 자동으로 실행할 수 있다.

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#32 WSGI  (0) 2021.10.15
#31 터미널 접속  (0) 2021.10.14
#29 AWS  (0) 2021.10.14
#28 검색과 정렬  (0) 2021.10.12
#27 마크다운(Markdown)  (0) 2021.10.11

 이제 pybo가 간단하지만 어느정도의 기능을 갖춘 웹페이지가 되었으니 다른 사용자들도 ip만 알고있다면 접속

가능하도록 서버를 구축해야한다.  직접 서버를 구축하는 방법도 있지만 개인용 pc로는 성능에도 한계가있고 방법도

쉽지 않기 때문에 여기서는 AWS(Amazone Web Services) 의 라이트세일 서비스를 사용하여 보다 쉽고 저렴하게

pybo를 배포해본다.

 

1. AWS 가입

 먼저 AWS 공식 홈페이지에서 계정을 만들어야한다. 

 

홈페이지에서 계정 생성을 누르면 위와 같은 화면을 볼 수 있다.  이메일 주소와 암호, 계정이름을 입력하고 진행한다.

 

사용 타입은 개인으로, 전체이름에는 서버의 이름을, 전화번호에는 국가번호와 휴대폰번호를 입력한다. 주소는 한국을

기준으로 국가는 대한민국, 첫 번째 칸에는 건물의 주소를, 두 번째 칸에는 동/층/호수 를 입력하고 시에는 ㅇㅇ구,

ㅇㅇ군, ㅇㅇ시 등의 정보를,  시, 도 또는 리전에는 대한민국을 입력해주면 된다.  juso.go.kr 등의 사이트에서 주소를

검색한 뒤 영문보기를 하면 쉽게 입력할 수 있다.  우편번호까지 입력하고 다음으로 진행한다.

 

결제정보를 입력하는 화면이 나온다. 2021년 10월기준 결제정보 확인을 위해 100원이 빠져나가는데 짧은시간내에

다시 입금되기 때문에 걱정할 필요는 없다.

 

이후부터는 카드와 전화번호의 인증절차만 거치면 AWS 코드가 발송되고 이를 입력하면 성공적으로 계정이 생성된다.

지원 플랜을 선택하라고 하는 창이 뜨면 무료인 기본 플랜을 선택하면 된다.  이후 콘솔에 로그인 버튼을 클릭하여

생성한 계정으로 로그인해준다.

 

 

2. AWS 라이트세일 인스턴스 생성3

로그인을 마치고 AWS 라이트세일 공식 홈페이지에 접속하면 위와 같은 화면이 뜬다.  필자의 경우 이미 인스턴스를

만들어두었기 때문에 Ubuntu-1 이라는 인스턴스가 존재하지만 처음 가입한 상태에서는 바로 인스턴스 생성 화면이

보일 것이다. 

 

플랫폼으로는 Linux/Unix 환경과 Windows 환경을 모두 지원한다.  여기서는 Linus 환경을 사용하기로 한다.

blueprint는 앱과 OS를 결합시킨 버전도 있고 OS만을 지원하는 버전도 있는데, 우린 이미 앱으로 django 를

사용하고있으니 OS Only 에서 개인프로젝트에 사용하기에 가장 무난한 Linux 환경인 우분투를 선택한다.

 

마지막으로 인스턴스 플랜으로 첫 3달간 무료지원을 해주는 플랜을 선택한다.  5달러, 10달러 플랜도 3달 무료를

지원하지만 여기서는 3.5달러의 가장 저렴한 플랜을 선택하기로 한다.

 

인스턴스를 생성하고나면 Running 이라고 표시된 위치에 Pending 또는 대기 중이라는 메시지가 떠있을 것이다.  

조금 기다리면 Running 또는 실행 중이라는 메시지로 바뀌면서 서버가 실행된다.

 

 

3. 서버시간 설정

AWS 콘솔에 로그인한 후 AWS 라이트세일 홈페이지에 접속해서 위의 동그라미친 셸 아이콘을 클릭하자.

 

그러면 우분투의 터미널과 같은 창이 열린다.  여기서 우리가 생성한 서버를 조작할 수 있다.

 

처음 서버의 시간은 UTC 기준으로 맞춰져있다.  한국 시간에 맞게 조정하려면 다음 명령어를 실행하자.

sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

Asia/Seoul 타임존의 심볼릭 링크를 생성하여 /etc/localtime 을 덮어씌우는 리눅스 명령어이다. 실행하고나서 다시

date 명령어를 실행하면 이제 정상적으로 한국시간이 표시되는 것을 확인할 수 있다.

 

 

4. 파이썬 설치 확인

 장고를 사용하기 위해서는 파이썬이 필요하다.  서버에 파이썬이 설치되어있는지 확인하자.

 

셸에서 python 을 실행하면 찾을 수 없다는 메시지가 나오지만 python3 을 찾아보라는 메시지가 떠서 python3 을 

입력해보니 정상적으로 설치가 되어있는 것을 확인할 수 있다.  설치된 것을 확인했으면 exit() 로 파이썬 셸을 종료한다.

 

 

5. 가상환경 설치

처음 프로젝트를 시작했을 때 처럼 가상환경을 구성해보자. 먼저 다음 명령어를 호출하여 우분투의 패키지들을

최신버전으로 업데이트하자.

 

sudo apt update

 

 

 

가상환경의 설치를 위해 python3-venv 패키지를 설치하자.

 

sudo apt install python3-venv

 

필자의 경우 이미 설치가 끝나있기 때문에 변경사항이 없다.  중간에 선택화면이 나타나면 y(yes) 를 선택해주면 된다.

 

 

홈 디렉토리(~) 에 파이보가 위치할 projects 디렉토리와 가상환경을 생성할 venvs 디렉토리를 생성한다.

 

mkdir projects
mkdir venvs

 

정상적으로 두 디렉토리가 만들어진 것을 볼 수 있다.

 

 

프로젝트 초반에 했던 것 처럼 다음 명령어들을 실행하여 venvs 디렉토리로 이동한 뒤 가상환경을 생성한다.

 

cd venvs
python3 -m venv mysite

 

 

 

다음 명령어들을 수행하여 mysite/bin 으로 이동한 뒤 activate 를 실행해준다.

 

cd mysite/bin
. activate

 

어디서든 가상환경을 벗어나려면 deactivate 를 실행해주면 된다.  이후의 작업은 가상환경 내에서 이뤄진다.

 

 

6. wheel 패키지, django, markdow 패키지 설치

 로컬 환경에서는 문제가 없었지만 서버 환경에서는 pip 로 파이보 관련 패키지들을 설치할 때 wheel 패키지 관련

오류가 발생할 수 있다고 한다.  다음 명령어들을 실행하여 먼저 wheel 패키지를 설치한 뒤 django 와 markdown

패키지를 설치해준다. 

 

pip install wheel
pip install django==<버전>
pip install markdown

 django 의 경우 ==으로 버전을 명시하여 설치한다.  필자의 경우 로컬에서 사용했던 버전인 3.2.6 버전을 쓰기 위해

pip install django==3.2.6 과 같이 실행하였다.

 

 

7. Pybo 설치

 이제 드디어 우리가 만들었던 Pybo를 설치할 차례이다.  지금까지 작업한 파이보 프로젝트의 파일들은

git 원격 저장소에 push 한 뒤 서버에서 clone 하는 것으로 손쉽게 가져올 수 있다.

 

 

cd ~/projects
git clone "https://github.com/<유저명>/<레포지토리명>.git <프로젝트이름>

위와 같이 push 해둔 pybo 프로젝트의 레포지토리에서 code 버튼을 클릭, url을 확인한 뒤 projects 디렉토리에서

git clone 명령어를 수행해주면 레포지토리에 저장된 프로젝트를 그대로 가져온다.

 

원격저장소에 올려둔 파일들이 모두 서버에 복사되었다.

 

 

8. 데이터베이스 생성

 하지만 아직 서버를 정상적으로 구동할 수는 없는 상태이다.  우리가 간이 db로 사용했던 db.sqlite3 는 당연하게도

원격저장소에 포함되어있지 않기 때문에 먼저 마이그레이션을 실행해줘야 한다. 

 

python manage.py makemigrations
python manage.py migrate

 

pybo/migrations 디렉토리에 makemigration 으로 만들어진 파일들이 모두 들어있다면 makemigrations 는 수행할 필요

없이 migrate 명령어만을 수행해도 마이그레이션이 완료되고 db.sqlite3 이 생성된 것을 확인할 수 있을 것이다.

데이터베이스 외에도 서버의 SECRET_KEY 값을 분리해둔 파일과 같은 원격저장소에 공유해선 안되는 종류의 파일들

또한 서버에는 존재하지 않는 상태이다. 이들 또한 서버에 전송하여 서버가 정상적으로 구동할 수 있는 환경을 조성하자.

 

 

9. 고정 IP 생성

 이제 pybo 서버는 구동 가능한 상태가 되었지만 다른 사용자들이 접속하기 위해서는 고정 ip를 발행해야한다. 

 

AWS 라이트세일 홈페이지에 접속해서 네트워킹 탭으로 들어가면 Create static IP 로 고정 IP를 생성할 수 있다.

인스턴스 선택 창에서 우리가 만들었던 인스턴스를 선택해주고 생성 버튼만 눌러주면 간단히 만들어진다.

 

 

만들어진 고정 IP에 들어가면 IP 주소를 확인할 수 있다. 이제 이 IP를 통해 서버에 접속할 수 있다.

 

 

10. 방화벽 설정

 pybo 서버의 포트번호는 8000 번이기 때문에 방화벽 규칙을 설정하여 8000번 포트를 개방해야한다.

 

 

AWS 라이트세일에서 만들어둔 인스턴스에 들어가 네트워킹 탭을 보면 위와 같이 방화벽 규칙을 추가할 수 있다.

 

포트번호에 8000 을 입력하고 생성하자.

 

이제 장고 서버를 8000 포트를 개방하도록 실행하면 외부사용자도 접속이 가능하다.

 

 

11. ALLOWED_HOSTS 추가

 그런데 서버를 실행하고 브라우저에서 고정 ip로 접속하면 DisallowedHosts 에러가 발생할 것이다. 이는 해당 웹서버를 

구동할 수 있는 호스트로 현재 ip를 등록해두지 않았기 때문에 생기는 문제이다. 

 

로컬 프로젝트에서 config/settings.py 를 위와 같이 수정한 뒤 commit 하고 원격 저장소에 push 한다.

ALLOWED_HOSTS 리스트에 발급받은 서버의 고정 ip를 문자열 형태로 넣어주면 된다. 

 

그리고 다시 서버쪽에서 git pull 명령을 실행하여 원격저장소의 변경사항을 서버에 반영해준다. 필자의 경우 이미

업데이트가 진행되어있기 때문에 변경사항이 없지만 변경사항이 있을 경우 정상적으로 반영해줄 것이다.

 

 

12. 서버 구동

다시한번 8000 포트를 개방하여 서버를 구동한다.

 

이제 정말로 고정 ip만 알고있다면 다른 사용자도 pybo에 접속할 수 있게 되었다.

 

 

13. AWS 라이트세일 사용종료

 2021년 10월 기준으로 AWS 라이트세일의 인스턴스중 3.5달러, 5달러, 10달러 플랜은 첫 3개월간 무료지원을 해준다.

기간이 지나고도 의도하지 않은 요금이 발생하지 않도록 사용을 중지하려면 인스턴스와 고정 IP를 삭제해야한다.

 

 

인스턴스의 경우 AWS 라이트세일 홈페이지에서 인스턴스 메뉴에서 삭제를 클릭하면 삭제 가능하다.

 

고정 IP의 경우 네트워킹 탭에서 마찬가지의 방법으로 삭제할 수 있다.

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#31 터미널 접속  (0) 2021.10.14
#30 settings.py 분리  (0) 2021.10.14
#28 검색과 정렬  (0) 2021.10.12
#27 마크다운(Markdown)  (0) 2021.10.11
#26 앵커  (0) 2021.10.11

이번에는 Pybo의 index 페이지에 검색기능과 정렬기능을 추가해본다.

 

1. 검색창 추가

검색창은 페이징 영역 아래쪽에 중간부분에 오도록 만들 것이다.  question_list.html 의 페이징 영역 아래부분을

위와 같이 수정해준다.

 

 

2. searchForm, 스크립트 코드 작성

그리고 검색영역 아래부분에 검색창에서 입력받은 내용을 뷰 함수에 전달하기 위한 폼을 만들어준다.

hidden 속성으로 검색어(kw)와 페이지번호(page) 데이터를 받아오는 폼이다.

 

지금까지 페이지번호를 직접 url로 요청했던 링크들도 수정해준다. 

 

<a class="page-link" href="?page={{ <페이지번호> }}">{{ <페이지번호> }}</a>

이와 같은 형태였던 링크들을

 

<a class="page-link" data-page="{{ <페이지번호> }}" href="#">{{ <페이지번호> }}</a>

이와 같이 변경한 것이다.

 

게시글, 답글, 댓글 삭제 기능을 구현할 때도 href 값을 #으로 하고 data-XXX 의 형태로 값을 저장만 해두었던 것을

기억할 것이다.  이번에도 그 때와 마찬가지로 스크립트 코드를 통해 이를 처리해야한다.  삭제 기능을 구현할 때와

마찬가지로 스크립트 블록 내에 자바스크립트 코드를 작성해준다. 

 

page-link 클래스의 링크가 클릭될 경우 data-page 로 저장된 페이지번호를 page 변수에 세팅해준 뒤 searchForm 을

제출한다.  searchForm 은 kw에는 값이 없으니 빈 문자열이, page에는 자바스크립트 코드에서 설정된 페이지번호가

들어간 채로 GET 방식으로 제출되어 뷰 함수에서 처리된다.

 

id가 btn_search 인 버튼이 클릭될 경우 kw클래스의 값을 가져와서 kw 변수에 세팅, page 변수는 모든 페이지에 대해

검색해야 하기 때문에 1로 세팅한 뒤 searchForm 을 제출한다.  page-link 때와 마찬가지로 searchForm 은 이 값들을

입력값으로 받아 GET 방식으로 제출하여 뷰 함수에서 이를 처리한다.

 

 

3. 뷰 함수 수정

이제 pybo/views 디렉토리의 base_views.py 를 수정하여 실제로 searchForm 을 처리해야한다.

 

먼저 django.db.models 의 Q 함수를 import 한다.  이 함수는 게시글 리스트에서 검색조건에 맞는 글만을

필터링하기 위해 사용된다.

 

request에서 키워드(kw) 값을 가져온다.

 

위와 같이 코드를 작성하여 question_list 의 항목들을 필터링한다.  각 게시글의 subject(제목), content(내용),

author.username(글쓴이 이름), answer.author.username(답글 글쓴이들의 이름) 에 kw가 포함되어있는 경우만을

필터링한 것이다.  icontains 대신 contains 를 사용할 경우 대소문자를 구분하여 검색결과를 반영할 수 있다.

 

마지막으로 index 페이지를 렌더링 할 때 넘겨줄 context 에 kw 와 page 도 추가한다.  이렇게 하면 검색 후

index 페이지에서도 내가 검색한 검색어가 그대로 검색창의 텍스트필드에 남아있으며 검색을 위해 페이지를 1로

세팅한 것도 반영된다.

 

 

 

검색 결과가 정상적으로 반영되는 것을 볼 수 있다.

 

 

4. 정렬 조건 선택창 추가

이제 정렬기능을 구현할 차례다.  먼저 정렬 기준은 최신순(작성된 날짜가 최신일수록 위에), 추천순(추천 수가 많을수록

위에), 인기순(답글 수가 많을수록 위에) 세 가지로 구현할 것이다.

 

검색창의 텍스트필드 좌측에 위와같이 선택박스를 생성한다.  so 값으로 설정된 선택지가 선택박스에 표시된다.

 

정렬 기능 또한 searchForm 에서 처리하도록 할 것이다.  정렬 조건인 so를 입력값으로 받아오도록 한다.

 

정렬 처리를 위한 스크립트 코드도 추가해준다. 정렬 조건인 so 값이 변경된 경우 so는 변경된 so값으로,

page는 1로 설정하여 searchForm 을 제출한다.

 

django.db.models 에서 이번에는 Count 함수를 import 한다.

 

request 에서 정렬 기준 so 값을 받아와 그에따라 정렬을 수행한다.  annotate 함수와 Count 함수를 사용하여 추천자

수와 답글 갯수를 구할 수 있다.  만약 추천자 수나 답글 갯수가 같다면 작성 날짜가 최신일수록 위에 오도록 하여

정렬한다.

 

페이지가 다시 렌더링된 후에도 선택한 정렬조건이 남아있도록 하기 위해서 so 값도 context 에 추가한다.

 

 

 

이제 정렬 기능이 정상적으로 동작하는 것을 확인할 수 있다. 

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#30 settings.py 분리  (0) 2021.10.14
#29 AWS  (0) 2021.10.14
#27 마크다운(Markdown)  (0) 2021.10.11
#26 앵커  (0) 2021.10.11
#25 추천 기능  (0) 2021.10.10

 일반적인 블로그 등에서 글을 작성할 때 텍스트를 진하게 표시하거나 하이퍼링크를 추가하거나 글머리 기호를 추가하는 등 다양한 시각효과를 줄 수 있다.  물론 마크업(Markup) 언어인 HTML을 이용해서도 가능한 일이지만 마크다운

이라는 마크업 언어의 경량버전 언어를 사용하면 보다 간단하게 텍스트를 원하는 형태로 표현할 수 있다.  블로그 외에도 Github 와 같은 많은 웹사이트들이 마크다운 문법을 사용한 글쓰기를 지원한다.

 

1. 마크다운 문법

 Pybo에 마크다운을 통한 글쓰기 기능을 추가하기에 앞서 마크다운 문법에 대해 간단하게 알아보자.

 

 ① 리스트

   말그대로 어떤 항목들의 목록을 나타내기 위해 사용된다.

* 항목 1
* 항목 2
* 항목 3

  이와 같은 방식으로 작성할 수 있으며

 

  실제 웹페이지에선 위와 같은 형태로 표시된다.

 

 

 ② 순서 리스트

   리스트와 동일하지만 항목들의 순서를 나타낼 필요가 있는 경우 사용한다.

1. 항목 1
1. 항목 2
1. 항목 3

  이와 같은 방식으로 작성할 수 있으며

 

  실제 웹페이지에선 위와 같은 형태로 표시된다.

 

 

 ③ 강조

   특정 텍스트를 강조표시하기 위해 사용한다.

일반텍스트 **강조할 텍스트** 일반텍스트

  이와 같은 방식으로 작성할 수 있으며

 

  실제 웹페이지에선 위와 같은 형태로 표시된다.

 

 

 ④ 링크

   텍스트에 하이퍼링크를 추가할 때 사용한다. 

[파이썬 홈페이지](http://www.python.org)

  이와 같은 방식으로 작성할 수 있으며

 

  실제 웹페이지에선 위와 같은 형태로 표시된다.

 

 

 ⑤ 소스코드

   코드블럭을 만들어 그 안에 소스코드를 표현할 때 사용한다.

```
def python():
	print('HelloPython')
```

  이와 같은 방식으로 작성할 수 있으며

 

  실제 웹페이지에선 위와 같은 형태로 표시된다.

 

 

 ⑥ 인용

   인용을 표시할 떄 사용한다.

> 인용할 내용

  이와 같은 방식으로 작성할 수 있으며

 

  실제 웹페이지에선 위와 같은 형태로 표시된다.

 

 마크다운의 문법은 이 외에도 다양하지만 더 자세한 내용에 대해서는 마크다운 문법 공식문서를 참조하자.

 

 

2. 마크다운 설치

 마크다운의 문법에 대해 간단히 알아보았으니 이제 Pybo에 마크다운 기능을 적용할 차례이다. 먼저 터미널에서

아래 명령어를 실행하여 마크다운 모듈을 설치하자.

 

pip install markdown

 

성공적으로 설치된 것을 확인할 수 있다.

 

 

3. 마크다운 필터 등록

 마크다운으로 작성한 문서를 HTML 문서로 변환하기 위해서는 템플릿에서 사용할 마크다운 필터를 작성해야한다.

 

이전 페이징의 구현을 위해 만들었던 pybo_filter.py 에서 markdown 모듈과 django.utils.safestring 의 mark_safe 함수를

import 한다.  그리고 mark 필터를 위와같이 작성하여 등록한다.  extensions 에는 마크다운 문법으로 글을 작성할 때

개행 시 공백문자를 두번 입력할 필요가 없도록 하기 위해 nl2br을, 마크다운 코드 표현을 위해 fenced_code를 넣어준다.

mark다운 모듈과 mark_safe 함수를 사용하여 입력받은 마크다운 코드를 해석하고 이를 HTML 코드로 변환한다.

 

question_detail.html 의 두 번째 라인에서 필터를 로드해준다.

 

그리고 아래쪽의 게시글 내용을 표시하는 코드를 위와 같이 수정하여 mark 필터를 적용하여 출력되도록 한다.

 

답글에도 마찬가지로 적용해준다.

 

 

4. 마크다운 적용 확인

이제 마크다운 필터 적용이 정상적으로 이루어졌는지 확인하기 위해 테스트를 해본다.

 

 

다른 것들은 잘 적용이 되지만 코드블럭과 인용 부분은 스타일이 적용되지 않아 적용된것이 확실히 보이지 않는 것을

볼 수 있다.

 

static 디렉토리의 style.css 에서 pre 태그와 blockquote 태그에 대한 스타일을 수정해준다.

 

이제 코드블럭과 인용 부분이 적용된 것을 쉽게 확인할 수 있다.

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#29 AWS  (0) 2021.10.14
#28 검색과 정렬  (0) 2021.10.12
#26 앵커  (0) 2021.10.11
#25 추천 기능  (0) 2021.10.10
#24 View 파일 분리하기  (0) 2021.10.10

1. 앵커(Anchor)

 현재 Pybo는 댓글이나 답글을 작성/수정하고나면 게시글 상세페이지로 리다이렉트되며 페이지 최상단으로 이동하기

때문에 자신이 작성한 답변을 확인하기 위해 스크롤을 내려야 한다.  Ajax 와 같은 비동기 통신기술을 사용하면 페이지의

리로드 자체가 발생하지 않기 때문에 자동으로 해결될 일이지만 여기서는 앵커(Anchor)를 사용하여 보다 쉽게 해결하려

한다. 하이퍼링크를 추가할때 사용햇던 <a> 태그가 바로 앵커 태그이다.  앵커 태그를 통해 다른 웹 페이지의 하이퍼

링크나 웹페이지 내 특정 부분으로 이동할 수 있다. 

 

2. 답글 앵커 추가

 특정 답글로의 이동을 위해서는 먼저 답글의 위치에 앵커태그를 추가해둬야한다. 

 

반복문으로 게시글에 달린 답글들을 출력하는 템플릿 코드에서 답글 하나의 시작부분에 앵커태그를 추가한다.

앵커태그의 name은 유일한 값이어야 하기 때문에 answer_<답글id> 의 형태로 하였다.

 

3. 답글 작성, 수정 후 앵커 위치로 리다이렉트

 이제 답글을 작성하거나 수정하면 해당 위치의 앵커로 이동하도록 리다이렉트 함수를 수정해야한다.

 

먼저 django.shortcuts 에서 resolve_url 을 import 한다.  url resolve 는 url 매핑이 의미하는 실제 url주소를 문자열로

반환하는 함수이다. 그리고나서 redirect 되는 주소를 <게시글상세페이지 주소>/#answer_<작성/수정한 답글id> 의

형태로 수정해준다. 이동할 url의 뒷부분에 #앵커이름 을 추가해주는 것으로 그 페이지의 앵커이름에 해당하는 부분으로

이동할 수 있다.

 

 

답글을 작성해보면 리다이렉트되며 작성한 답글의 위치로 바로 이동하는 것을 확인할 수 있다.

 

 

4. 댓글에 앵커기능 추가

 답글과 동일한 방식으로 댓글에도 앵커기능을 추가할 수 있다.

 

 

게시글과 답글의 댓글영역 시작부분에 앵커를 추가해준다. 

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#28 검색과 정렬  (0) 2021.10.12
#27 마크다운(Markdown)  (0) 2021.10.11
#25 추천 기능  (0) 2021.10.10
#24 View 파일 분리하기  (0) 2021.10.10
#23 댓글  (0) 2021.10.07

이번에는 사용자가 게시글이나 답글에 추천(좋아요)을 할 수 있는 기능을 추가해본다.

 

1. 모델 변경

 당연히 먼저 Question 모델과 Answer 모델에 추천기능에 사용될 속성을 추가해야한다.

 

pybo/models.py 에서 Question, Answer 모델에 voter 속성을 추가한다.  그런데 저상태로는 마이그레이션 시에 에러가 발생한다.  User 모델에 연결된 속성이 author 와 voter 로 두 개이기 때문에 User 모델을 통해 Question 이나 Answer

인스턴스에 접근할 때 둘 중 어느것을 참조해야할지 모호해지기 때문이다. 

 

 

이를 해결하기 위해 author 와 voter 속성에 각각 related_name 인자를 추가해줘야 한다. 이제 어떤 유저가 작성한 게시글을 볼 때는 user.author_question.all(), 추천한 게시글을 볼 때는 user.voter_question.all() 과 같이 표현할 수 있다.

 

모델 수정이 완료되었으니 makemigrations 와 migrate 명령어를 실행하여 마이그레이션을 수행해준다.

 

 

2. 게시글 추천

 이제 본격적으로 게시글 추천 기능을 만들어야 한다.  먼저 게시글 상세페이지에 추천 버튼부터 생성해보자.

 

 먼저 추천영역과 기존의 게시글 내용과 답글을 표시하던 영역을 분리하기 위해 더 큰 영역을 만들어 추천 영역을

col-1 속성으로, 기존 부분을 col-11 속성으로 하는 것으로 추천:기존내용의 비율이 1:11로 나타나도록 하였다.

 

추천 링크의 href 값을 #으로 하고 data-uri 인자를 넣은 것으로 알 수 있듯이 여기서도 자바 스크립트 코드를 사용하여

정말 추천할것인지 확인창을 띄울 것이다. 삭제를 위해 만들었던 코드에서 메시지 내용을 수정하고 .delete 를

.recommend 로 수정하는 것으로 간단하게 기능을 구현할 수 있다.

 

pybo/urls.py 에 vote_question 에 해당하는 url 매핑도 추가해준다.  이전 게시글에서 views.py 파일을 분리했기 때문에

아직 생성하진 않았지만 뷰 함수인 vote_question 이 정의될 vote_views.py 파일의 import 문을 작성하고 vote_views.py

에 정의된 뷰 함수임을 명시하며 매핑을 추가해준다.

 

그리고 실제로 views 디렉토리에 vote_views.py 파일을 위와 같이 작성한다.  추천 또한 로그인한 사용자만이 게시글마다

1인당 한번에 한해서 추천이 가능하도록 하며 본인이 작성한 게시글을 추천하려고 할 경우 에러메시지를 출력한다. 

작업이 끝나면 게시글 상세 페이지로 리다이렉트 시켜준다.

 

이제 게시글 본문 옆에 받은 추천 수와 추천 버튼이 생겼음을 확인할 수 있다.  

 

추천 버튼을 누르면 추천할 것인지 확인 메시지가 나타나며

 

본인의 게시글을 추천할 경우 에러메시지가 표시된다.

 

다른 계정으로 로그인하여 추천할 경우 정상적으로 추천수가 올라가는 것을 확인할 수 있다.

 

 

3. 답글 추천

게시글 추천을 이미 구현해보았으니 답글 추천을 구현하는 것도 간단하다. 빠르게 구현해보자.

 

모델의 수정은 이미 게시글 추천을 구현할 때 마쳐두었기 때문에 바로 추천 영역을 만들어준다.  게시글 때와 완전히

같은방식으로 작성하고 question.voter.count 를 answer.voter.count 로, data-uri 값에서 uri 매핑과 넘겨줄 id를

answer 에 해당하는 것으로 바꿔주면 된다.

 

pybo/urls.py 에 url 매핑도 추가해준다. 

 

vote_views.py 에 vote_answer 함수를 위와 같이 구현해준다. 게시글 추천 함수에서 question 을 answer 로 바꿔주는

것만으로 완성이지만 redirect 시에 question_id 를 통해 게시글 상세 페이지로 이동해야 하기 때문에 answer.id 가

아니라 answer.question.id 를 넘겨주는 것에만 주의하면 된다.

 

이제 답글에도 정상적으로 추천기능이 동작하는 것을 확인할 수 있다.

 

 

4. 게시글 목록 페이지에서 추천수 표시하기

 게시글 목록 페이지에서도 추천수가 표시되도록 수정해보자.

 

question_detail.html 에서 테이블 헤더에 추천 항목을 추가하고 badge 형태로 question.voter.count 를 표시하도록 한다.

수정하는 김에 가운데 정렬 해주는 것이 보기 좋은 항목들은 가운데 정렬하여 표시하도록 수정해주었다.

 

이제 게시글 목록 페이지에서 게시글의 추천 수를 볼 수 있다.

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#27 마크다운(Markdown)  (0) 2021.10.11
#26 앵커  (0) 2021.10.11
#24 View 파일 분리하기  (0) 2021.10.10
#23 댓글  (0) 2021.10.07
#22 수정과 삭제  (0) 2021.10.07

Pybo 에도 슬슬 많은 기능이 추가되면서 pybo.views.py 파일의 크기가 제법 커졌다.  간단한 프로젝트이기 때문에 아직까진 큰 문제가 없지만 더 많은 기능이 추가된다면 한 파일에 너무 많은 함수가 공존하게되어 관리가 어려워질 것이다.

이번에는 views.py 파일을 분리하는 방법을 알아본다. 

 

1. 카테고리별 view 파일 생성

먼저 views.py 에 몰아넣어놨던 함수들을 카테고리화하여 별도의 파일들에 정의할 것이다. 현재 pybo/views.py 에

정의된 14개의 함수들을 다음과 같이 카테고리화 한다.

  • base_views.py (기본 관리)
    • index
    • detail

 

  • qeustion_views.py (게시글 관리)
    • question_create
    • question_modify
    • question_delete

 

  • answer_views.py (답글 관리)
    • answer_create
    • answer_modify
    • answer_delete

 

  • comment_views.py (댓글 관리)
    • comment_create_question
    • comment_create_answer
    • comment_modify_question
    • comment_modify_answer
    • comment_delete_question
    • comment_delete_answer

 

pybo 디렉토리 내에 views 디렉토리를 생성하여 그 안에 위 카테고리에 따라 함수를 별도의 파일에 정의하고

import 문을 정리해준다.(PyCharm 기준 Ctrl + Alt + O)  원래 같은 디렉토리에 있었던 models.py 나 forms.py

파일의 경우 view 디렉토리 내부로 파일이 이동하면서 상위디렉토리에 위치한 파일이 되었기 때문에 

from ..models ~ 와 같은 형태로 import 문을 변경해야한다.

 

마지막으로 views 디렉토리 내의 __init__.py 에 위와같이 분리한 파일내의 모든 함수를 import 해주는것으로 나머지

코드의 수정 없이도 기존처럼 사이트가 잘 작동한다.

 

 

2. views/__init__.py 파일 제거

 그런데 위의 방법에는 한가지 중대한 문제가 있다.  view의 어떤 함수가 어느 파일에 속해있는지 알 방법이 없다는

것이다.  특정 기능을 수정하기 위해서는 그 기능이 정의된 파일을 찾기위해 views 디렉토리 내의 모든 파일을 열어볼

필요가 생긴다.  이를 해결하기 위해서는 불편하더라도 views 디렉토리의 __init__.py 를 삭제한 다음 뷰 함수들이

호출된 파일들에 직접 import 문을 작성해줘야 한다.

 

pybo/urls.py 를 위와같이 수정해준다.  

 

config/urls.py 의 index 에 해당하는 매핑도 위와같이 수정해준다.

 

이제 어느 뷰 함수가 어느 파일에 정의되어있는지 한눈에 알 수 있다.  

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#26 앵커  (0) 2021.10.11
#25 추천 기능  (0) 2021.10.10
#23 댓글  (0) 2021.10.07
#22 수정과 삭제  (0) 2021.10.07
#21 글쓴이 표시  (0) 2021.10.04

1. 댓글 모델 작성

 이번에는 게시글과 답글에 댓글을 달 수 있는 기능을 추가해보기로 한다.

 

먼저 pybo/models.py 에 Comment 모델을 추가해준다. Answer 모델과 거의 유사하지만 답글의 경우

게시글과 답글 모두에 달릴 수 있기 때문에 외래키로 Question과 Answer의 객체 둘 다 받을 수 있어야 하며

둘 중 한쪽에만 값이 저장될 것이기 때문에 null=True, blank=True 로 설정하여 비워둘 수 있도록 해야한다.

 

모델이 변경되었으니 makemigrations 와 migrate를 수행해준다.

 

 

2. 게시글 댓글

 게시글에 댓글을 등록하는 기능을 추가한다.

 

먼저 question_detail.html 에서 게시글의 수정,삭제 버튼을 표시한 위치 바로 옆에 댓글창을 만들어준다. 이번에는 

댓글의 표시, 작성, 수정, 삭제 기능까지 모두 한번에 구현해보자.

 

댓글창의 디자인을 위해 부트스트랩 적용이후 사용하지 않았던 static 디렉토리의 style.css 를 위와 같이 수정해준다.

 

pybo/urls.py 에 새로 추가한 기능들에 사용된 url 매핑을 추가해준다.

 

pybo/forms.py 에 댓글을 입력받기 위한 CommentForm을 추가해준다.

 

pybo/views.py 에 댓글을 저장하기 위한 comment_create_question 함수를 구현한다.  답글을 저장하는 함수와 매우

유사하기 때문에 어렵지 않게 만들 수 있다.

 

댓글을 작성하기 위한 템플릿 comment_form.html 을 만들어준다.  이 역시 답글 작성을 위해 만들었던

answer_form.html과 거의 다르지않다.

 

댓글 수정을 위한 comment_modify_question 함수를 구현한다. 게시글이나 답글 수정과 거의 동일하다.

 

댓글 삭제를 위한 comment_delete_question 함수를 구현한다. 게시글이나 답글 삭제와 거의 동일하다.

 

이제 pybo에 접속해보면 로그인 상태에서게시글에 댓글을 달 수 있게 된것을 확인할 수 있다.

 

댓글이 정상적으로 등록되는 것을 볼 수 있다.

 

수정이나 삭제 기능도 정상적으로 작동하는 것을 확인할 수 있다.

 

3. 답글 댓글

 이제 답글에도 댓글 기능을 추가해주자.  이 작업은 게시글에 댓글기능을 추가하는것을 거의 그대로 반복하는

것이기 때문에 자세한 설명은 생략하도록 한다.

 

question_detail의 답글 부분에 댓글영역 추가

 

pybo/urls.py 에 url 매핑 추가

 

pybo/views.py 에 댓글 작성, 수정, 삭제 함수를 구현

 

이제 답글에도 댓글기능이 정상적으로 추가된 것을 확인할 수 있다.

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#25 추천 기능  (0) 2021.10.10
#24 View 파일 분리하기  (0) 2021.10.10
#22 수정과 삭제  (0) 2021.10.07
#21 글쓴이 표시  (0) 2021.10.04
#20 모델 변경  (0) 2021.10.04

1. 수정 일시

 이번에는 게시글을 수정하고 삭제하는 기능을 추가할 것이다. 먼저 게시글과 답글에 수정 일시 정보를 넣기 위한

modify_date 속성을 추가해보자.

 

 pybo/models.py 를 위와 같이 수정하여 게시글과 답글 모델에 modify_date 속성을 추가해준다.  modify_date 는

수정사항이 발생했을 때만 생성되는 데이터이기 때문에 어떤 조건으로든 값을 비워둘 수 있음을 명시하기 위해

null=True, blank=True 로 설정한다.

 

물론 모델이 변경됐기 때문에 makemigrations 와 migrate 도 잊지말고 실행해줘야 한다.  author 속성을 추가했을 때와

달리 비워둘 수 있는 속성이기 때문에 별다른 문제없이 수행된다.

 

 

2. 질문 수정

 이제 게시글 수정 기능을 구현해보자.

 

먼저 templates/pybo/question_detail.html 을 위와 같이 수정하여 로그인한 유저가 이 게시글의 작성자일 때에 한해서

게시글 수정 버튼이 나타나도록 한다.

 

pybo/urls.py 에 위와 같이 pybo:question_modify 에 해당하는 url 매핑을 추가한다.

 

pybo/views.py 에 question_modify 함수를 추가한다.  비정상적인 접근을 대비해서 게시글 작성유저 본인이 맞는지

한번더 확인하여 본인이 아니라면 오류메시지를 띄우고 게시글 상세 페이지로 이동하고 작성자 본인이 맞다면

question 인스턴스와 함께 게시글 작성 페이지로 이동하도록 한다.

 

오류 메시지를 표시하기 위해 quesiton_detail.html 을 위와 같이 조금 더 수정한다. 

 

이제 유저 본인이라면 수정 버튼이 생기고 수정 버튼을 누르면 게시글 수정 페이지가 잘 보이는 것을 확인할 수 있다.

 

또한 url을 통해 비정상적으로 수정 페이지에 접근할 경우 수정 권한이 없다는 오류메시지를 띄우는 것도 확인 가능하다.

 

 

3. 질문 삭제

 다음은 질문을 삭제하는 기능을 구현할 차례이다. 

 

방금 전 수정 버튼을 추가한 자리 아래에 위와 같이 삭제 버튼도 만들어준다. 삭제버튼의 경우 정말로 삭제할 것인지

확인을 해야하기 때문에 href 를 #으로 하고 data-uri에 삭제 페이지 url을 저장, 클래스에 delete 속성을 넣어준다.

 

삭제 확인 메시지창이 뜨도록 하기 위해서는 자바 스크립트 코드가 필요하다. 그리고 자바 스크립트 코드를 실행하려면

jQuery 라이브러리를 로드할 필요가 있다.  우리는 이전에 부트스트랩의 적용을 위해 이미 jQuery 라이브러리를

base.html에 포함시켜 두었다.  base.html을 위와같이 조금 수정하여 자바스크립트의 호출이 반드시 jQuery 로드 이후에

오도록 하자.

 

그리고 question_detail.html 에서 body 블록 아래에 script 블록을 추가하여 삭제를 확인하는 메시지가 뜨도록 한다.

 

pybo/urls.py 에 data-uri 에 넣어준 question:delete 에 해당하는 url 매핑을 추가해준다.

 

pybo/views.py 에 question_delete 함수도 구현해준다.  수정과 마찬가지로 유저 본인확인을 한번 더 진행한 뒤

삭제가 이뤄지도록 하였다.

 

유저 본인의 게시물일 경우 삭제 버튼이 나타나고 클릭 시 확인 메시지가 나타난다.

 

삭제를 확인할 경우 게시글이 정상적으로 삭제된 것을 볼 수 있다.

 

 

4. 답변 수정

 이제 답글에도 수정, 삭제기능을 구현해야한다.  기본적인 흐름은 게시글과 같으나 답변 작성 화면은 원래 게시글

상세 페이지에 딸려있는 형태이기에 수정을 위한 템플릿을 별도로 만들어야한다.

 

question_detail.html 을 수정하여 게시글 상세 페이지의 답글에 수정 버튼을 추가한다.

 

pybo/urls.py 에 answer:modify 에 해당하는 url 매핑을 추가한다.

 

pybo/views.py 에 answer_modify 함수를 추가한다.

 

위와 같이 question_form.html 을 참조하여 answer_form.html 을 작성한다. 

 

이제 정상적으로 답글 수정이 가능한 것을 확인할 수 있다.

 

 

5. 답변 삭제

 답글 삭제도 게시글의 삭제와 마찬가지로 이루어진다.

 

먼저 question_detail.html 에서 답글의 수정버튼 옆에 삭제 버튼을 추가해준다.  게시글 삭제와 마찬가지로 href 를

#으로 하고 url은 data-uri 에 넣어준다.  또한 삭제버튼이 눌린것을 감지하기 위해 class에 delete 속성도 추가한다.

 

pybo/urls.py 에 answer:delete 에 해당하는 url 매핑을 추가한다.

 

pybo/views.py 에 answer_delete 함수를 위와같이 구현한다.  삭제되면 index로 나가야했던 게시글과 달리

답글은 삭제할 경우 answer.question.id 에 해당하는 question_detail 페이지로 이동하도록 한다.

 

삭제 확인을 위한 자바스크립트 코드는 이미 삽입되어있기 때문에 추가적인 작업이 필요하지 않다.

 

답글 삭제 기능이 정상적으로 동작하는 것을 확인할 수 있다.

 

 

6. 수정 일시 표시

 마지막으로 게시글과 답글에 수정이 발생한 경우 수정 일시를 표시하는 기능을 추가하자.

 

question_detail.html을 위와 같이 수정하여 게시글과 답글의 작성일시 옆에 수정 일시를 표시하도록 한다.

 

수정된 게시글과 답글에 정상적으로 수정일시가 표시되는 것을 확인할 수 있다.

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#24 View 파일 분리하기  (0) 2021.10.10
#23 댓글  (0) 2021.10.07
#21 글쓴이 표시  (0) 2021.10.04
#20 모델 변경  (0) 2021.10.04
#19 계정 생성  (0) 2021.10.01

1. 질문 목록 페이지 수정

 이제 로그인한 유저만이 게시글과 답글을 작성할 수 있게 되었으니 게시글과 답글에 글쓴이를 표시해야한다.

우선 질문 목록 템플릿에 글쓴이를 표시해보자.

 

테이블 헤더의 텍스트가 가운데 정렬되도록 class 속성을 수정하고 제목 부분의 너비를 지정해준 뒤

제목 뒤쪽에 글쓴이 항목을 추가해준다.  그리고 나서 for 문에서도 제목은 왼쪽정렬 되도록 class 속성을

수정해주고 제목 뒤쪽에 글쓴이를 추가해준다.

 

이제 질문 리스트에서 게시글의 작성자를 확인할 수 있다.

 

 

2. 질문 상세 페이지 수정

 다음으로 질문 상세 템플릿에 글쓴이를 표시해보자.

 

templates/pybo/question_detail.html 을 위와 같이 수정하여 게시글과 답글의 작성일시를 표시하던 뱃지의

텍스트를 왼쪽으로 정렬시키고 작성일시 위에 작성자도 표시되도록 한다. 

 

이제 게시글과 답글 모두 작성자를 확인할 수 있다.

'개인 프로젝트 > Django-mysite' 카테고리의 다른 글

#23 댓글  (0) 2021.10.07
#22 수정과 삭제  (0) 2021.10.07
#20 모델 변경  (0) 2021.10.04
#19 계정 생성  (0) 2021.10.01
#18 로그인/로그아웃  (0) 2021.09.30

+ Recent posts