저번에 깃을 이용해 저장소를 생성하고 소스코드를 관리했다. 이것을 원격 저장소로 관리하기 위해 깃허브를 사용하자. 먼저 깃허브에 가입을 하자.
new repository 를 해서 새로운 원격 저장소를 생성하주자. 그렇게 하면
이러한 URL이 나오는데 이것을 로컬 저장소와 연결해주는것이다.
터미널에 git remote add origin <깃허브에있던 URL> 을해서 연결하자.
이 명령을 한 후 오류가 발생하지 않으면
git push -u origin main 명령어를 치면 깃허브의 Username 과 Password 를 치는곳이 나오는데 Username 을 치고 Password 를 쳐야한다. 하지만 맥 기준으로는 깃허브의 비밀번호가 아닌 token을 입력해줘야한다. 이 토큰은 깃허브에서 세팅-개발자세팅-토큰 에서 토큰을 만들어서 나오는 토큰을 복사해 Password 입력칸에 붙여넣기 하면된다.
Settings - Developer settings 에 들어가 Personal access tokens 에 Tokens(classic)을 누르면 나오는 화면에서 Generate new token 을 누르면 이름을 설정하고 체크하는게 여러개 나오는데 사실 뭐가 뭔지 잘 모르겠어서 일단 다 체크했다. 그렇게 하면 코드같은게 나오는데 그것을 복사 붙여넣기 하면 된다.
이제 깃허브를 보면 정상적으로 파일들이 원격저장소로 올라간것을 알 수 있다. 여러번 사용해보면서 익숙해져야 할 것 같다.
코드를 작성하다보면 수정과 삭제가 빈번하게 발생하고, 과거에 삭제한 부분을 살리거나 언제 어느부분을 수정했는지 확인해야할 때 가 있기도 하다. 여러명이서 작업할 때는 소스코드를 여러명이서 수정하고 왜 수정했는지 이유가 필요할 때가 있다. 이를 위해 Git 을 설치하고 사용해보자.
터미널에
git --version 이라고 쳐서 버전이 나오면 다운로드가 되어있는것이다. 안나온다면
Homebrew 를 설치하고 brew install git 을 해서 git을 다운로드하자.
먼저 저장소(repository)을 만들자.
그리고 git status 명령을 실행하자.
git status 는 현재 저장소의 상태를 출력해 준다. 아직 관리되지 않고 있는 파일(Untracked files)들을 보여주고 git add 명령을 이용하여 관리할 파일들을 추가하라고 알려준다.
git add 명령 수행전에 깃으로 관리해야 할 파일들을 고려해야 한다. 직접 작성한 mysite, pybo 디렉토리 등은 깃으로 관리해야 할 대상이 맞지만 .idea, sqlite3 파일은 사용자별, 시스템 별로 달라지기 때문에 깃으로 관리하면 안된다. .idea는 사용자 설정을 저장하는 파이참 전용 파일이고, db.sqlite3 파일은 SQLite의 데이터베이스 파일이다. 예를 들어 여러 명이 같은 저장소에서 작업할 때 .idea 파일을 누군가가 변경한다면 내가 설정했던 파이참 설정 내용이 다른 사람의 것으로 변경될 수 도있다. 이런 문제를 방지하기 위해 .gitignore 파일을 작성해 깃으로 관리하지 않을 대상을 설정해 줘야한다.
projects\mysite\.gitignore 위치에 새로운 파일을 생성하자.
이제 하려던 git add 명령을 해보자.
git add * 명령을 하자.
git add 뒤에 * 을 추가해 명령어를 수행한 이유는 모든 파일을 추가하겠다는 의미이다.
그 후 git status 를 해보자.
이렇게 하면 깃 스테이지 영역에 추가된 파일을 확인할 수 있다. 깃은 저장소에 변경 사항을 바로 저장하지 않고 스테이징 이라는 단계를 거친다. 스테이징은 변경 사항을 저장소에 저장하기 직전 단계에 올려놓는 개념이다. 먼저 git add 로 스테이징에 올려놓고 git commit 으로 스테이지에있는 파일을 저장소에 저장한다.
이제 git commit 명령으로 저장하자.
git commit 명령을 수행하면 먼저 이메일 주소 와 사용자명을 설정하라고 적혀있다. 본인의 이름과 이메일 주소를 사용하자.
그 후 git commit -m '파이보 프로젝트 최초 커밋'
git status 를 하면 잘 적용된것을 볼 수 있다.
그런데 점프 투 장고 저자는 오류가 나지 않았었지만 나는 .gitignore 을 설정 했는데 modified : .gitignore 하면서 오류가 났었는데
git rm -r --cached . git add .
명령어로 git 의 cache 를 초기화 해주니 해결 되었다.
이제 변경사항이 없고 작업 공간이 깨끗하다는 정보를 확인할 수 있다.
이번엔 base.html 템플릿 파일의 <title> 엘리먼트를 다음과 같이 바꿔보자.
projects\mysite\templates\base.html 를 수정하자.
수정 한 후 git status 명령을 해보자.
수정된것이 있다고 한다.
git diff 를 해보자.
q 를 입력하면 창에서 나갈 수 있다.
무엇이 수정되었는지 확인할 수 있다.
- 는 삭제된 부분, + 는 추가된 부분이다.
코드의 변경 내역을 되돌리고 싶을 때는 git restore 명령을 수행하면 된다.
파일의 이름은 git status 명령을 했을때 출력된 파일명을 기준으로 적으면 된다. git restore 를 해보면 다시 내용이 복구된것을 확인할 수 있다.
다시 <title>파이보</title> 로 변경하고 git commit 명령을 해보자.
그럼 오류와 함께 git add 명령을 하거나 또는 git commit -a 명령을 하라는 메세지가 나온다. -a 옵션은 커밋할 때 add 명령도 함께 처리하라는 옵션이다.
현재 이 튜토리얼을 따라 장고를 배우고 있는데, 이 책에서 구현할 기능은 여기까지지만 우리가 평소에 사용하는 게시판을 생각해보면 알듯이 더 다양한 기능들이 있다. 댓글, 카테고리, 비밀번호 찾기 및 변경, 프로필 등 이있다. 이런 것들은 나중에 따로 공부해보면 추가해보겠다. 그 전에 이 책의 저자가 더 다양한 파이보 기능들을 구현해 놓은 파이보 게시판이있다.
게시판에서 검색기능은 필수이다. 검색의 대상은 제목, 질문의 내용, 질문의 작성자, 답변의 내용, 답변의 작성자가 있다.
이런 조건으로 검색하려면 질문 목록을 조회하는 부분을 다음처럼 수정해야 한다. 일단 눈으로만 보자.
from django.db.models. import Q
kw = request.GET.get('kw', '') # 검색어
if kw: question_list = question_list.filter( Q(subject__icontains=kw) | # 제목 검색 Q(content__icontains=kw) | # 내용 검색 Q(answer__content__icontains=kw) | # 답변 내용 검색 Q(author__username__icontains=kw) | # 질문 글쓴이 검색 Q(answer__author__username__icontains=kw) # 답변 글쓴이 검색 ).distinct()
Q 함수는 OR 조건으로 데이터를 조회하기 위해 사용하는 함수이다. 제목,내용,글쓴이를 or 조건으로 검색하기위해 사용했다. 그리고 filter 함수 뒤에서 사용된 distinct 조회 결과에 중복이 있을 경우 중복을 제거하여 리턴하는 함수이다.
위 코드에서 kw 는 화면으로 부터 전달받은 검색어이다. 그리고 kw 값은 POST 가 아닌 GET 으로 읽도록 했다. GET 은 가져온다는 개념이고, POST 는 수행한다는 개념이라고 볼수있다. GET 은 글늬 내용에 대한 목록을 보여주는 경우나, 글의 내용을 보는 경우이고, POST 는 글의 내용을 저장하고, 수정할 때 사용한다.
kw = request.GET.get('kw', '') # 검색어
이처럼 작성되었기 때문에 kw 는 다음처럼 GET 방식으로 전달되어야 index 함수에서 읽을 수 있다.
http://localhost:8000/?kw=파이썬&page=1
만약 kw 를 GET이 아닌 POST 방식으로 전달하는 방법으로 한다면 page 파라미터도 POST 방식으로 전달되어야 한다. 하지만 그렇게 한다면 새로고침이나 뒤로가기 등을 했을 때 만료된 페이지라는 오류를 만난다. POST 방식은 동일한 POST 요청이 발생할 경우 오류를 발생시키기 때문이다. 그러므로 게시물 목록을 조회할 때는 GET 방식을 사용하는 것이 좋다.
이제 화면에서 kw 와 page 를 동시에 GET 방식으로 호출하는 방법에 대해서 알아보자.question_list.html 템플릿에 검색어를 입력할 수 있는 텍스트 창을 추가하자.
projects\mysite\templates\pybo\question_list.html 에 추가하자.
<table>태그 상단 우측에 검색어를 입력할 수 있는 텍스트창을 생성하였다. 맨 밑에 있던 질문 등록하기 버튼은 검색창의 좌측으로 이동했다. 그리고 자바스크림트에서 이 텍스트창에 입력된 값을 읽기 위해 다음처럼 id 속성을 추가했다.
<input type="text"
id="search_kw"
class="form-control" value="{{ kw|default_if_none:'' }}">빨간 줄로 그은 부분은 삭제해주자.
그리고 page 와 kw 를 동시에 GET 으로 요청할 수 있는 searchForm 을 다음과 같이 추가하자.projects\mysite\templates\pybo\question_list.html 에 추가하자.
GET 방식으로 요청해야 하므로 method 속성에 "get" 을 설정했다. kw 와 page 는 이전에 요청했던 값을 기억하고 있어야 하므로 value에 값을 대입했다. 이전에 요청했던 kw와 page의 값은 index 함수로부터 전달될 것이다. action 속성은 '폼이 전송되는 URL'이므로 질문 목록 URL인 {% url 'index' %} 를 지정했다.
기존 페이징 처리하는 부분도 ?page=1 처럼 직접 파라미터를 코딩하는 방식에서 값을 읽어 폼에 설정할 수 있도록 변경해야한다.
projects\mysite\templates\pybo\question_list.html 을 변경하자.
모든 페이지 링크를 href 속성에 직접 입력하는 대신 data-page 속성으로 값을 읽을 수 있도록 변경했다.
그리고 page, kw 파라미터를 동시에 요청할 수 있는 자바스크립트를 다음과 같이 추가하자.
projects\mysite\templates\pybo\question_list.html 에 추가하자.
작성한 자바스크립트 코드를 살펴보자면,
만약 다음과 같이 class 속성 값으로 'page-link' 라는 값을 가지고 있는 링크를 클릭하면
마크다운으로 작성한 문서를 HTML 문서로 변환하려면 템플릿에서 사용할 마크다운 필터를 작성해야 한다. 이전에 sub 필터를 작성했던 pybo_filter.py 파일에 다음과 같이 mark 필터를 추가하자.
projects\mysite\pybo\templatetags\pybo_filter.py 에 추가하자.
mark 함수는 markdown 모듈과 mark_safe 함수를 이용해 입력 문자열을 HTML 로 변환하는 필터 함수이다. 마크다운에는 몇 가지 확장 기능이 있는데 파이보는 위처럼 nl2br 과 fenced_code 를 사용했다. nl2br 는 줄바꿈 문자를 <br> 로 바꾸어주고 fenced_code 는 위에서 살펴본 마크다운의 소스코드 표현을 위해 필요하다.
답글을 작성하거나 수정한 후에 항상 페이지 상단으로 스크롤이 이동되어 작성한 답변을 확인하려면 다시 스크롤을 내려서 확인해야 한다. Ajax같은 비동기 통신 기술을 사용할 수 도 있지만 보다 쉬운 방법으로 이 문제를 해결해 보자. HTML 에는 URL 호출시 원하는 위치로 이동시켜 주는 앵커 태그가 있다. 예를 들어 HTML 중간에 <a id="django"></a> 라는 앵커 태그가 있다면 이 HTML 을 호출하는 URL 뒤에 #django 라고 붙여주면 해당 페이지가 호출되면서 해당 앵커로 스크롤이 이동된다. 이를 적용해 보자.
먼저 답변에 앵커기능을 추가해 보자.
projects\mysite\templates\pybo\question_detail.html 을 수정하자.
답변 작성, 수정시에이동해야할 앵커 태그를 추가했다. 답변이 반복되어 표시되는 for 문 바로 뒤에 추가했다. name 속성은 유일한 값 이어야 하므로 answer_{{ answer.id }} 같은 답변 id 를 사용했다.
이제 답변을 등록하거나 수정한 뒤 지정한 앵커 태그로 이동하도록 코드를 수정하자. 다음은 답변 등록 또는 답변 수정을 한 뒤 사용했던 기존 코드의 일부이다.