* 추가할 기능 구현 (게시판)

- 조회수 조작 방지 기능



* 추가할 기능 구현 (인증)

- 소셜 인증


--------------------------------------------------------------------------------------


  조회수 조작 방지에 관해 어떻게 해결해야할까 고민하던 중 오늘 자료실의 좋아요 기능을 만들면서 해결책이 가늠이 잡혔다. 하지만 이번 일지에서는 구현하지 못하였다.


  이번 일지에서는 자료실을 추가하였다. 게시판과 똑같다. 다만 파일 업로드, 다운로드 기능이 새로웠고, 조회수 대산 좋아요 기능을 추가하였다.




  자료실 모델이다.


< model >


  게시판과 똑같다. 다른 점은 FileField 가 추가되었다.


< urls.py >


  게시판과 같고 다른점은 좋아요 기능 구현을 위한 url이 추가되었다.


자료실의 모습이다.


< 자료실 모습 >


  게시판과 같은 모습이지만 맨 오른쪽에 좋아요 수를 보여주고 있다.


자료실 업로드는 큰 어려움이 없었는데 업로드된 파일을 다른 사용자가 다운로드해주는 기능을 추가해야했다.


< 다운로드 기능 >


  DEBUG 모드에서는 단순히 URL 주소를 넘겨주면 직접 접근이 가능하다. 하지만 실제 배포하였을 때는 직접 접근이 안되기 때문에, 다운로드 기능을 추가해주어야한다. file_url 에서 맨 앞 글자를 지운 이유는 이상하게도 업로드된 사진을 웹에 보여주는 것과는 동작이 달랐기 때문인데 문제를 분석하다보니 url 다루는 차이가 있었다.


  file의 경우 앞에 / 문자가 없어야 잘 동작했고 사진의 경우 / 문자가 있어야 잘 동작했다. 그래서 / 문자를 settings.py 에서는 넣어서 설정을 하고 파일 다운로드 기능에서는 위와 같이 [1:] 을 사용해 맨 처음 문자를 빼고 넣어주었다.



< 다운로드 >


  다운로드를 클릭하니 다운로드 되었다.



< 다운로드 된 모습 >



  다음으로 좋아요 기능이다.


< like_tools 추가 >


  먼저 사용자의 프로필에 like_tools를 추가해주었다. 이는 ManyToMany 필드로 연결했다.



< 토글 기능 >


  토글기능은 현재 사용자의 좋아요 리스트에서 해당 포스트 자료가 존재하면 remove 해주고 존재하지 않으면 add로 해당 포스트 자료를 추가해준다.



< html >


  마찬가지로 좋아요 리스트에 있다면 좋아요를 누른것이므로 Unlike를 출력해주고 없으면 아직 누르지 않은 것으로 Like 를 출력하여 토글 버튼이 되도록 하였다.



< 좋아요 클릭 >



< 좋아요 클릭한 모습 >


  좋아요를 클릭하면 Unlike로 바뀐다.



< 좋아요 수 출력 >


  좋아요 수는 해당 자료를 좋아요 누른 사람들의 수를 count 하여 출력해준다.


* 서버 호스팅

- MySQL 연동

- AWS 구축 및 환경 구축

- 호스팅 및 DNS 등록


* 추가할 기능 구현 (게시판)

- 조회수 조작 방지 기능



* 추가할 기능 구현 (인증)

- 소셜 인증


* 추가할 기능 구현 (게시판)

- 댓글 수정기능 -> 댓글 삭제 기능

- 조회수 조작 방지 기능

- 게시글 삭제 기능


* 추가할 기능 구현 (인증)

- 소셜 인증


==========================================


  댓글 수정말고 댓글 삭제 기능을 넣었다. 댓글 같은 경우 수정할 바에 차라리 지우고 다시 쓰도록 의도하였다.


  먼저 작업 들어가기전에 갑자기 아이디어가 떠올라 개선한 점이 있다. 바로 리다이렉트부분이다. 기존 같은 경우 게시글을 수정하거나, 게시글에서 댓글을 작성한 후에 게시글 리스트로 리다이렉트 된다. reverse를 써서 제자리에 오도록 하려했으나 (F5기능) circular import 문제 때문에 구현하지 못했었다.


  그런데 그냥 템플릿에 넘겨주면 되지 않나? 라는 생각이 들어 이 부분을 해결하였다.


< render로 변경 >


  템플릿을 지정해주고 context 안에 post를 담아서 보내주었다.



< 개선된 게시글 >


  이제 이 자리에서 바로 글을 수정해도 이 페이지며, 댓글을 달아도 이 페이지로 남는다.


  그런데 이상한 점을 추가적으로 포착했다. 바로 개행이 안된다는 점이다. 위 사진을 보면 분명 내가 Update 마다 줄을 바꿔줘서 넣었는데 개행처리가 안됬다.


  이 점에 대해 검색을 해보니 HTML에서 개행을 처리 안해서 그렇다고 한다. 개행을 <br> 로 바꿔주면 된다. 여기서 linebreaksbr 을 사용하면 <br>로 바뀐다고 한다.



< linebreaksbr >


  확인해보면 다음과 같다.


< 개행처리 되는 모습 >



  이제 본격적으로 구현하고자 하는 기능 구현이다. 먼저 게시글 삭제 기능이다. 이 기능은 직접 구현하지 않고 CBV를 이용하여 구현하였다. 다만 함부로 삭제되면 안되므로 현재 로그인된 사용자가 게시글을 작성한 사람과 같은지 검증하기 위해 filter를 이용하여 검색된 쿼리만 삭제하도록 구현하였다.


< PostDeleteView >


  테스트해본다.!


< 삭제 테스트 >



< 삭제 확인 팝업 >


  정말 삭제할 것인지 물어본다.


  그 후 정말 삭제할 것인지 다시 한번 물어보는데 이는 DeleteView에 있는 기본 기능에서 템플릿만 만들어서 이어주었다.


< 재재확인 >



< 삭제된 글 >


  글이 정상적으로 삭제 되는 것을 확인하였다.



  다음으로 댓글 삭제이다. 댓글 삭제도 CBV를 이용하고 싶었으나, pk 종류가 두개가 들어오는데 이를 처리하는 부분에서 계속 에러가 나서 직접 view를 작성하였다.



< comment_delete view >


  post와 comment 둘 다 얻는다. 그 이유는 comment는 삭제하기 위한 것이고, post는 다시 원래 있던 페이지로 돌아가기 위해서이다.



< 댓글 삭제 테스트 >


  맨 위의 댓글을 지워보았다.



< 댓글 삭제 확인 >



  댓글이 정상적으로 삭제되었다. 




* 추가할 기능 구현 (게시판)

- 조회수 조작 방지 기능



* 추가할 기능 구현 (인증)

- 소셜 인증


* 추가할 기능 구현 (게시판)

- 댓글 기능

- 조회수 기능

- 게시글 삭제 기능


* 추가할 기능 구현 (인증)

- 소셜 인증


------------------------------------


  오늘은 댓글 기능과 조회수 기능을 추가하였다.


  추가적으로 게시판의 모양을 테이블로 조금 더 그럴싸하게 만들었다.


< 게시판 표 작성 >


  게시판 모델 HTML을 가져와 사용했고, 컨텐츠는 전달받는 post에서 뽑아서 뿌려주었다.



< 게시판 모양 >


  다음으로 댓글 기능을 추가하였다.


다음은 댓글 Model이다.


< Comment Model >


  writer를 Profile과 연결해주었다. 또 post와도 연결해주었다.


  다음은 템플릿에서 댓글 출력 코드이다. 


< 댓글 출력 코드 >


  Comment 모델에서 post를 외부키로 연결할 때 related_name을 comments로 정의해주어서 comments로 접근할 수 있다.


  여기에 사진은 캡쳐하지 않았지만 comment.comment_writer로 닉네임을 출력할 수 있었던 이유는 내가 Profile 모델을 정의하면서 __str__ 을 overwrite해서 닉네임을 출력하게 만들었기 때문이다.


< 댓글 출력 화면 >



  다음으로 댓글 쓰기 기능을 만들었다. 쓰기의 경우 기존 detail 보는 템플릿에서 폼을 추가해주고 해당 폼을 처리해줄 view를 만드는 과정으로 진행했다.



< form 생성 >


  post 와도 외부키가 연결되어있기 때문에 post의 pk가 필요하다.



< comment_write view >


  POST 메서드일 경우만 처리하게 만들었다. 이 경우 post를 pk로 뽑아내고 현재 로그인한 사용자의 user를 가져와 연결된 Profile을 작성자와 연결해준다. 그 후 각 내용을 Comment 로 생성해주면 된다.



< 테스트 댓글 작성 >



< 댓글 작성 확인 >


  다음으로 댓글의 개수를 출력해주었다.


< 댓글 수 >


  이 댓글 수를 새주는 것은 all 대신 count를 이용하면 되었다.



  다음으로! 조회수 기능이다.! 

나는 Detail View(CBV)를 사용하였는데, 인터넷에 보니 CBV를 사용할 경우 처리해야할 게 많아서 보통 다른 lib를 이용한다고 들었다. 그런데 내가 일단 구현해 보았다.



< 조회수 증가 함수 생성 >


  @property를 이용하면 템플릿에서도 사용할 수 있다. 조회수를 1 늘리고 저장한다.



< 템플릿에 삽입 >


  이렇게 되면 해당 화면이 불려질때마다 해당 post의 조회수가 1씩 증가한다.



< 조회수 증가 테스트 >

  


  테스트해보니 문제가있었다...

해당 템플릿이 로드 될 때마다 조회수가 증가하다보니, F5를 연달아 누르면 조회수가 막 올라간다... 


  이 기능을 세션을 가지고 처리했던 것 같은데 자세히 다시 알아보고 처리해야겠다.



* 추가할 기능 구현 (게시판)

- 댓글 수정기능

- 조회수 조작 방지 기능

- 게시글 삭제 기능


* 추가할 기능 구현 (인증)

- 소셜 인증



  Django 프로젝트에서 게시판 프로젝트를 시작한다. 인증 부분에서 소셜인증, 회원정보 수정을 제외하고는 전부 구현하였다. (나머지 기능은 차차 구현할 것이다.)



  오늘은 게시판에서 게시글들을 출력하고 게시글을 들어가서 확인하는 것까지 구현하였다.


  먼저 시간 설정을 해주었다. Post 모델을 정의하여 게시글을 만들었다. 이 때 작성일시를 자동으로 현재 날짜시간을 기록하게 하였는데, 이 때 settings.py 에서 설정해주어야할 것이 있다.


< settings.py 설정 >


  이 변수를 False로 설정해야 settings.py에서 설정한 시간대를 프로젝트 전체에서 사용할 수 있다.



  Post 모델을 정의하였다.


< Post 모델 >


  이 모델은 게시글이다. 작성자를 CharField로 설정한 이유는 사용자의 프로필에서 nickname을 가져와서 문자열로 저장하려고 하기 위해서이다.



< urls.py >


  다음으로 urls.py를 설정해준다. 기본적인 게시글 리스트와 디테일을 만들었다. 그리고 추가적으로 글 쓰기와, 글 수정을 만들었다.



< CBV를 이용한 View >


  글 리스트와 디테일은 CBV를 이용하여 쉽게 구현하였다.



< 게시글 목록 보기 >



< 게시글 자세히 보기 >


  다음으로 글 작성하는 것을 만들었다. CreateView (CBV)를 이용할 수 있었지만, 나는 작성자에 사용자의 프로필에 있는 닉네임을 넣어줄 것이고 또한 메세지를 출력해주고 싶었기에 직접 view를 만들었다.


< post_write view >


  글쓰기 뷰를 만들고 테스트해보았다.



< 글 작성 테스트 >



< 글 작성 성공 메세지 알람 >


< 글 작성 리스트에서 확인 >



< 글 작성 내용 보기로 확인 >



  다음으로 작성한 글에 대한 내용을 수정하는 것이다.


< post_update view >


  여기서 인증부분이 필요했다. 글은 아무나 수정하면 안되기 때문이다. 로그인한 사용자의 정보에서 프로필을 가져와 프로필에 있는 닉네임과 게시글 작성자를 비교하여 같으면 수정을 허락하고 같지 않으면 경고를 해준다.



< 글 수정 테스트 >



< 글 수정 성공 메세지 알람 >


< 글 수정 확인 >


  오늘 일지의 마지막으로는 유저 확인기능에 대해서 정리할 것이다. 게시글에서 작성자가 나오는데 해당 작성자에 대해 알아볼 수 있는 기능을 추가하기로 했다. 작성자를 클릭하면 작성자의 정보가 나오게 하는 것이다.



< user_select_info view >


  개인 정보 확인하는 것을 그대로 따왔다.



< urls 추가 >


  개인정보의 경우 로그인정보를 이용하여 정보를 가져오면 되지만 다른 사용자의 정보를 출력하기 위해서는 해당 사용자의 정보를 넘겨줘야한다. 그래서 나는 작성자를 넘겨 주기로 했다.



< 작성자 확인 테스트 >

  tfa 를 클릭해보았다.



< 다른 사용자 정보 확인 >


  다른 사용자의 정보를 확인 할 수 있었다.



=============================


* 추가할 기능 구현 (게시판)

- 댓글 기능

- 조회수 기능

- 게시글 삭제 기능


* 추가할 기능 구현 (인증)

- 소셜 인증



지금 까지만든 설문지페이지에서 오늘은 form을 작성해 볼 것이다.

 HTML에서 form은 데이터를 전달 하는 기능을 한다.
우리는 설문지에서 설문 선택지를 선택하고 버튼을 클릭하면 선택한 선택지의 정보를 담아서 웹 페이지에 전달할 것이다.

이 내용은 DB에 저장될 것이므로, POST 방식으로 보내게 할 것이다.


(detail.html)


detail.html 템플릿은 question 객체를 받는다.
받은 question 객체에서 질문 내용인 question_text를 h1 태그로 찍어준다.

그리고 에러메시지가 있으면 해당 에러 내용을 출력해준다.

그 다음 부터는 form 태그이다.
그런데 중간에 csrf 토큰이 보일 것이다. 우리는 form 을 사용하여 데이터를 전달할 것이기 때문에 CSRF 공격에 대해 생각하고 있어야한다. 장고에서 대신 CSRF 공격에 대해 예방하는 기능이 있는데
{% csrf_token %} 만 작성하면 된다. (나중에도 form 문에는 이 문구를 적어넣어야한다. )
해당 question객체에서 선택지들을 전부 가져온 후 for 문을 돌면서 radio 버튼과 선택지 내용을 출력한다.

웹페이지를 실행시켜서 직접 확인해보자!



(form 페이지)


질문 내용이 위에 찍혀있고 선택지들이 버튼과 함께 나열되어있는 것을 볼 수 있다.

위에 form 코드를 다시 보면 url vote로 이동하라고 action에 나와있다.

url vote는 우리가 작성한 polls/urls.py를 확인하면 알 수 있다.


(vote)


vote이름을 가진 주소패턴에 해당 question.id가 조합이 되면 어떤 주소가 된다.
보면 views.vote를 실행하게 되어있다.

그렇다면 views.vote를 작성해주자!


(views.vote)


우리는 question_id를 주소에서 전달받게 된다. 전달 받은 question_id를 pk로 사용하여 해당 질문 객체를 가져온다.
그 후 선택된 선택지를 가져오는데 request객체 안에 POST에 담겨있다. 우리가 POST로 전달했기 때문이다. POST 속에 choice=### 이런식으로 담겨온다. choice변수에 담긴 값을 pk로 선택된 질문을 가져온다. 그 후 선택된 질문객체에서 투표수를 1 증가시키고 저장한다.
그리고 Redirect한다. reverse를 사용해서 url 주소를 만든다.
polls 이름 영역의 urls.py에 정의 되어있는 results 이름의 주소 패턴을 가져오고 인자로 question.id를 조합하여 특정 url을 만드는 것이다. 그 주소로 리다이렉트한다.

그렇다면 처리된 결과를 확인하는 results의 화면도 만들어보자.


(views.results)


위에서 리다이렉트된 주소는 views.results를 호출한다. polls/urls.py를 확인하면 알 수 있다.
이 뷰에서는 질문 객체를 가져오고 이 질문 객체를 가지고 polls/results.html 템플릿을 보여준다.

보여주는 results.html 템플릿은 아래와 같다.


(results.html)


질문 객체에서 각각의 선택 내용과 투표수를 출력하는 템플릿이다.

실행해서 확인해보자.



(실행 확인)


확인해보니 잘 된다!

질문 객체를 가져오고, 질문 객체를 가지고 템플릿으로 전달하고 등등
어떻게 보면 이것 또한 루틴한 작업이다.
그래서 이번에는 제네릭 뷰를 이용해서 위의 페이지를 똑같이 만들어 볼 것이다.

제네릭 뷰에는 리스트뷰와 디테일뷰가 있다.
리스트뷰는 말 그대로 리스트들을 보여주는데 사용하고
디테일뷰는 우리가 detail view를 만들었던거와 같다.

먼저 제네릭뷰를 사용하기 전에 polls/urls.py를 수정해줘야한다.


(polls/urls.py)


제네릭뷰에서는 pk로 전달 받기 때문에 pk로 바꾸어 주었다.
그리고 호출하는 것이 각각의 뷰에서 as_view() 함수를 호출한다.
우리는 views에 위에서 사용한 클래스를 만들어줘야한다.

이어서 view를 수정해 줄 것이다. 제네릭 뷰를 이용해 수정한 코드는 아래와 같다.


(제네릭 뷰)


각각의 클래스를 만들었다.
template_name은 우리가 사용할 템플릿 위치를 알려준다.
그리고 model은 어떤 모델이 적용될 것인지 지정해주는 것이다.
DetailView의 경우 question 변수가 자동으로 제공된다. 그러나 ListView의 경우 자동 생성된 컨텍스트변수는 question_list이기 때문에 우리가 템플릿에서 사용했던 변수 이름으로 맞춰주기 위해 context_object_name의 변수로 지정해주었다.

ListView에서 get_queryset을 가지고 쿼리를 날리는데 우리는 최근 5개 글을 볼것이므로 해당 함수를 덮어쓴 것이다.

실행해서 웹페이지에서 똑같은 동작인지 확인해보자



(동작 확인)


같은 동작을 하는 것을 확인 할 수 있다.

(* 참조 - https://docs.djangoproject.com/ko/2.0/intro/tutorial04/)

'Web > Django Project' 카테고리의 다른 글

Simple SignUp  (1) 2018.07.25
Simple Login/Logout  (0) 2018.07.24
Django Tutorial - Views ( Template와 연결 )  (0) 2018.02.01
Django Tutorial - 관리자 생성 및 페이지보기  (0) 2018.01.31
Django Tutorial - Model  (0) 2018.01.31
이제는 views.py를 작성해 볼 것이다.

views 와 url을 연결하는 것은 지난 포스팅에서 다루었다.
이제 그 views.py를 작성 할 것이다.

개발환경이 바뀌었다.!!!!
우분투 너무 느렸는데, CentOS로 옮겼다. 아주 쾌적하고 좋았다. :)

우리는 4개의 view를 만들어야했다.
1. index : 설문지 리스트를 보여주는 view
2. detail : 특정 설문지에 들어가서 선택지들을 보여주는 view
3. vote : 선택지를 선택한 것에 대한 처리를 담당하는 view

4. results : 설문 결과를 보여주는 view


(views.py)


위와 같이 간단히 작성할 것이다.
지금 단계로는 우리가 계획한 view를 바로 설계할 수 없다.
위에 작성한 코드들은 해당 페이지와 연결을 하는 것을 해보기 위해서이다.
보면 view에 인자들을 살펴봐야한다.

첫번째 인자는 request 로 요청에 대한 객체이다.

두번째 인자는 넘겨 받는 인자인데, 우리가 urls.py를 작성할 때 url 주소에서 파싱한 내용들이다.


(polls/urls.py)


polls/urls.py 에 주소 패턴에 넘겨주는 인자가 있다.

이대로 실행해보자.
polls/3  의 주소를 요청하게 되면

뒤에 3이 question_id 라는 변수에 들어가서 넘겨가는 것이다.



(실행 화면)


3이라는 숫자가 question_id로 넘어가서 화면에 저렇게 표시 되는 것을 확인 할 수 있다.


이제 실제로 view에서 무언가를 처리하는 것을 넣을 것이다.
위에서는 단순하게 인자를 넘겨받는 것 까지만이었다.

최근 설문지 5개를 가져와서 출력하는 것을 해보자!



(views.index)


latest_question_list에 최신의 설문지 5개를 가져온다. 반복자형식이다.
그리고 해당 설문지의 설문내용을 하나씩 붙여서 output에 넣고
그 output을 화면에 출력해주는 코드이다.

확인!


(확인)


확인해보니 설문내용이 출력되는 것을 확인 할 수 있었다.

장고는 모델과 뷰, 템플릿이 따로 관리되는 MTV 구조를 가지고 있다.
그에 따라 우리도 템플릿을 만들어서 여기서 보여주는 것을 해볼 것이다.

템플릿은 settings.py 파일에서 INSTALLED_APP 디렉토리에서 하위 templates 디렉토리를 탐색한다.
고로 우리는 polls/templates 를 만들어야한다.

여기서 다시 polls 디렉토리를 만든다.
정리하면,
polls/templates/polls
이렇다.

이유는 장고가 템플릿을 찾을 때 이름이 일치하는 첫번째 템플릿을 가져온다.
그렇다면 동일한 템플릿 이름이 다른 APP에도 있다면? 어떻게 구분할 수 있을까?
그렇기 때문에 templates디렉토리 아래에 해당 어플 이름으로 디렉토리를 하나 더 만들어 주어서
템플릿에 이름을 구분시켜주는 것이다.

polls/templates/polls/index.html 을 만들자!



(polls/templates/polls/index.html)


위 템플릿은 latest_question_list 를 넘겨받는다.

코드 설명
latest_question_list에서 하나씩 가져와서 question에 넣으면서 반복한다.
question의 id 값을 이용해 링크 걸린 문구를 출력한다.

만약 가져올 설문이 하나도 없다면
설문이 없다고 출력한다.

이렇게 템플릿을 만들었으니

우리는 view에서 이 템플릿과 연결해야한다.



(polls/views.index)


template에 템플릿을 가져오고
context 에 latest_question_list 변수를 지정한 사전형 자료를 담아둔다.

그리고 template.render를 해주면 된다.



(결과)


이렇게 실행하게 되면
웹 페이지에서 링크로 출력되는 것을 확인 할 수 있다.

여기서 의문이 든다.
템플릿 로드하고, 변수 저장하고 템플릿 렌더해서 HttpResponse로 넘겨준다.
너무 루틴하지 않은가?
우리의 파이썬이 이걸 가만 놔둘리 없다.

단축기로 render라고 만들어두었다.
이 모든 과정을 한방에 해준다.

단축기를 사용해보자.



(단축기 사용)


render를 사용하면 위의 과정을 한번에 해준다.
단순히 템플릿을 지정해주고, 넘겨줄 변수를 사전형으로 만들어서 넘겨주면된다.

views에서 처리해야할 일이 또 뭐가 있을까?
바로,
에러처리다.

웹 페이지에서 대표적인 에러는 바로 404 에러이다.
해당 웹 페이지가 없는데 요청하는 것이다.
예를 들어 /polls/24  -> 만약 id가 24가 없다면 해당 페이지는 준비 되지 않은것이다.

404 에러 처리를 해보자!



(404 에러처리)


파이썬의 try except 구문을 사용한다.
해당 쿼리를 날려서 설문지를 가져오는데 만약 그게 없다면
404 에러를 반환한다.

실행하기 위해 detail.html을 만들어야하는데 형식상 만드는 것이므로 지금은 아주 간단히 작성한다.



(polls/templates/polls/detail.html)


없는 인덱스로 실행해보자.


(404 에러)


우리가 적은 Question does not exist 보이는가?
우리가 404 에러 처리를 하였다.

그렇다면 여기서도 또 의문이 든다.
try except 구문
왠지 많이 자주 쓰일 것이다.

그렇다!
이것 또한 단축기로 만들었다.!!!!
get_object_or_404 를 이용하면 해당 객체를 가져오는데 만약 없다면 404 에러를 내는 

우리가 위에서 했던 것을 한방에 해주는 함수다.



(단축기 사용)


실행해본다.



(실행 결과)


똑같이 404 에러가 떴다.
다만 에러 문구는 다르다!

이제 detail.html 템플릿에서

선택지를 보여주는 작업을 해볼 것이다.



(polls/templates/polls/detail.html)


해당 템플릿에서
question 객체를 받았다.
설문지에서 선택지를 전부 가져와서 하나씩 choice에 넣고
choice의 선택지를 출력해주는 것을 반복하는 코드이다.

실행해보면

(실행)


선택지들이 나열되어 나온다.


index 템플릿에서 detail 템플릿을 호출하였다.



(index 템플릿)


index 템플릿에서
/polls/ 
이렇게 url주소가 하드 코딩되어있다.

그렇다면 만약 detail 템플릿의 url이 바뀌면
이렇게 하드코딩된 주소를 찾아서 일일히 다 바꿔야할까?
그렇기 때문에 url 주소를 간편히 쓸수 있는 것이 있다.


(하드코딩 제거)


위처럼 {% url '이름' %} 이렇게 쓰면 된다.

그렇다면 저 url은 뭘까?


(urls.py)


우리가 urls.py에서 마지막 인자로 name 인자를 둔 것이 기억날 것이다.
이것이 우리가 url패턴을 각각 이름으로 정한것이다.

그렇기에 detail url을 쓰고 싶다면
{% url ' detail' %} 이렇게 쓰기만 하면 되는 것이다.

그렇다면 이 이름이 겹치는 것을 생각해봐야한다.
우리는 APP을 여러개 만들 건데 그 url마다 이름을 다 다르게 해야하는 건 너무 힘든 일이다.
다른 APP에 detail이라는 url 이름이 있을 수 있기 때문이다.

이걸 방지하기 위해 app_name을 지정해 줄 수 있다.



(APP 이름 지정)


위 처럼 app_name을 지정해주면 polls에서 사용하는 detail 이라고 알 수 있다.

그렇다면 당연히 아까 적은 url 표기도 바꾸어 주어야한다.


(url 표기 변경)


polls:detail
이렇게 바꾸면 된다.

(* 참조 - https://docs.djangoproject.com/ko/2.0/intro/tutorial03/)



이번에는 관리자를 생성한 후 관리자 페이지를 확인해 볼 것이다.

먼저!

관리자 계정을 생성한다!


(관리자 계정 생성)


명령어는 위와같고, 각자 계정과 비밀번호를 설정해주면 된다.

관리자 페이지란 장고에서 제공하는 기본적인 관리페이지이다.
우리는 이 페이지에서 우리가 만든 프로젝트를 관리할 수 있고 db도 쉽게 관리할 수 있다.

페이지는 /admin 으로 접속하면 된다.



(관리자 페이지)


아까 생성한 관리자 계정으로 접속한다.



(관리자 로그인)


로그인을 하면 위와 같은 화면이 나온다.

그런데?
우리가 아까 만든 model 정보는 없다..!
그렇다.
연결해야한다.

polls/admin.py로 가주자.



(polls/admin.py)


해당 파일을 위와 같이 작성한다.
register 함수로 Question 모델을 등록하는 것이다.

다시 접속해보면?


(관리자 페이지)


관리자 페이지에서 POLLS가 생성되고 아래 Question 항목이 생긴것을 볼 수 있다.

클릭해보면 아래와 같다.


(DB 수정)


해당 DB의 내용들을 볼 수 있고, 수정할 수 있고 추가할 수도 있다.
DB를 관리자 페이지에 연동시켜주면 나중에 DB관리도 장고에서 제공해주는 서비스를 이용하여 아주 편리하게 관리할 수 있다.

(* 참조 - https://docs.djangoproject.com/ko/2.0/intro/tutorial02/)


장고는 DB를 모델이라는 개념으로 관리를 한다.

우리는 데이터의 테이블을 하나의 model로 만들어주기만 하면
장고가 테이블도 생성해주고 기타 일을 해준다.

기본적으로 장고는 sqlite db를 사용한다. 나중에 다른 db와 연동하는 것도 공부하여 포스팅할 것이다.

지금은 장고의 모델 개념을 익히는데 집중을 할 것이다.

mange.py의 migrate 명령은 현재 db에서 수정된 부분을 적용시켜주는 역할을 한다. 모델을 확인하고 모델이 수정된 부분이 있으면 그거에 맞춰서 db를 적용시켜준다.

(초기 migrate)


처음 migrate를 하면 위와 같이 나온다.
우리는 아무 모델도 만들지 않고 그랬는데 뭘 적용하는거지?
장고는 기본적인 db 파일들이 있다. 관리자 정보, 인증 정보 세션정보 등등이 있다. 기본적인 db 정보들을 db에 필요하면 테이블도 만들고 알아서 적용시켜준다.

그렇다면 우리가 모델을 한번 직접 만들고 확인해보자.
지난 포스팅에서 우리는 polls 이라는 투표 APP 을 생성했다. 그렇다면 여기에 필요한 DB 테이블이 무엇일까?
기본적으로 질문들을 저장하는 테이블이 필요할 테고, 해당 질문에 대한 선택지들에 대한 테이블이 필요할 것이다.

그렇다면 Question과 Choice 모델을 2개 만들어보자.


(Question, Choice)


두 클래스 모두 model을 상속받아 생성한다.
기본적으로 model의 속성 필드가 있다.
CharField는 문자열이 저장되는 필드
DateTimeField는 날짜 정보가 저장될 수 있는 필드
IntegerField는 정수가 저장되는 필드
등등 있다. 이는 JSP나 다른 웹프로그래밍에서 DB를 생성해보았다면 이해하기 쉬울 것이다. 뒤 인자들도 쉽게 이해할 수 있을 것이다.
다만 다른점중 하나는 첫번째 인자를 선택하에 사람이 읽기 좋은 필등명으로 설정해줄 수 있다.
여기서는 pub_date를 보자. 여기서 필드를 생성할 때 첫번째 인자가 date published 라는 문자열로 설정되어있다. 우리는 해당 필드를 date published 라고 설정한 것이다.

그렇다면 이렇게 모델을 생성해주고 무엇을 해야하나?
여기서 이제 migrate 명령이 필요하다. 하지만 현재 우리 APP이 프로젝트로 포함되어있지 않다.!

포함시켜보자!


(포함시키기)


프로젝트명/프로젝트명/settings.py 에 들어가보면
INSTALLED_APPS 가 있는데 여기에 추가해야한다.
PollsConfig 클래스는 polls/apps.py 파일에 존재한다. 그러므로 경로는
'polls.apps.PollsConfig' 가 된다. 이 경로를 추가해주면 된다.

이제 migrate를 할 것이다.
우리는 직접 migrate하기전에 makemigrations를 이용해 과정을 살펴볼 것이다.

makemigrations 를 하게되면 변경된 부분을 migrate하기 전에 db를 위한 명령들이 있는 파일들로 만든다.


(makemigration)


polls에 대해 makemigrations을 해주니 하나의 파일이 생겼다.
이 파일 속에는 sql 쿼리들이 담겨있다.

확인해보면


(sql 쿼리)


위처럼 쿼리들이 저장되어있고, migrate를 하게 되면 위의 쿼리들이 날라가게 되는 것이다.

migrate!


(migrate)


migrate를 하게 되면 아까 생성된 파일들이 db에 적용이 된다.

이제 생성된 DB에 내용을 추가하는 것을 shell을 이용해 추가해볼 것이다.


(쉘 실행)


그 후 모델을 생성해준다.



(모델 생성)


모델에 내용을 채워서 생성해준다.

q에 Question 객체를 생성했다. 확인해보자.


(Question 객체 확인)


객체를 확인해보면 해당 내용들이 보인다.
save() 명령을 통해 DB에 저장할 수 있다.

객체를 확인해보자.


(객체 확인)


Question object (1) ..
우리가 알아볼 수 없다. 객체를 우리가 알아볼 수 있는 문자열로 보이게 하기 위해 조치를 취할 것이다.

이건 단순히 우리가 쉘에서 보기 편하게 하기 위해서가 아닌 나중에 관리자 페이지에서 해당 DB를 관리할 때 보기 편하게 하기 위해서이다.


(추가 내용)


위에서 만들었던 모델에 __str__ 을 오버라이드한다.

Question 모델에 메서드를 하나 추가해보자.



(메서드 추가)


최근에 발행된 질문인지 확인할 수 있는 메서드이다.

그리고 다시 쉘을 실행한다.


(확인)


아까보다 훨씬 보기 좋게 나온다. (질문내용을 나오게 출력했다.)

그리고 추가한 메서드도 확인해본다.



(추가 메서드 확인)



우리가 추가한 메서드도 잘 동작하는 것을 확인했다.

그렇다면 해당 질문에 선택지를 추가하고 마무리 하겠다.!



(선택지 추가)


선택지를 추가하였다.


( *참조 - https://docs.djangoproject.com/ko/2.0/intro/tutorial02/)


장고의 튜토리얼이다.

투표 APP을 만들 것이다. Project 안에는 여러가지의 APP이 있을 수 있다. 각각의 역할을 하는 APP이다. 여기서는 APP을 만드는 것을 해볼 것이다.



(APP 생성)


APP 생성은 manage.py 를 통해서 한다.

앱을 생성하면 다음과 같은 디렉토리 구조가 생긴다.



(생성된 디렉토리)


polls 디렉토리가 생겼다.

간단하게 웹페이지에서 해당 APP을 확인해 볼 것이다.
보여주는 것에 대한 처리를 담당하는 것이 views.py이다.

그러므로 우리는 views.py를 수정하여 해당 페이지에 들어가면 간단한 문구가 찍혀 나오게 할 것이다.



(views.py 작성)


HttpResponse 를 import하고 사용했다.
우리가 지금 만든 views.py에서 index는 아주아주 간단한 일을 하고 있다.
단순히 요청이 들어오면 위에 간단한 문구를 Http 응답으로 보내는 일이다.
HttpResponse는 Http 응답 페이지를 만들어서 보내주는 함수이다.

그렇다면 우리는 우리가 만든 views.py가 실행되야 해당 페이지에 문구를 띄울 수 있다.
우리는 url을 통해서 해당 페이지에 접근한다.
그러므로 url과 우리가 만든 views.py의 index를 연결해야한다.

urls.py를 만들어야한다.


(urls.py 생성)


해당 urls.py는 polls 디렉토리 안에서 생성하였다. 그리고 아래와 같이 작성한다.



(polls/urls.py)


해당 파일에서는 views 를 import 했다. 우리가 방금 작성한 index를 연결하기 위해서이다.
경로를 보면 '' 으로 아무것도 없다.
url에 아무것도 없으면 views.index랑 연결하라는 뜻이다.
옆에 name 인자는 해당 경로를 index 라는 이름으로 지정하는 것이다.
나중에 해당 url을 우리는 이 이름으로 불러와서 쓸것이다.

우리의 목적은 (우리사이트주소)/polls 에 접속하면 해당 index 페이지가 뜨는 것이다.(간단한 문구를 가진 페이지)
그러나 우리는 현재 빈문자열, 즉 아무것도 없는 경우에 index를 연결하였다.

순서가 조금 바뀌었지만,
이제 우리가 작성한 urls.py를 원본 urls.py에 연결해야한다.

(프로젝트 urls.py)



프로젝트이름/프로젝트이름/urls.py는 url 설정하는 파일이다.

여기에 우리는
path('polls/', include('polls.urls')), 줄을 추가하였다.
이 말은 polls 경로로 요청이 들어오면 include 하라는 뜻이다.

과정을 설명하자면
(우리사이트주소)/polls 로 요청이 들어오게 되면 이 파일에서 검사를 한다.

polls/ 라는 첫번째 패턴에서 걸리게 된다.

그러면 polls/ 까지 잘라버린다. 그렇게 되면 남은 url은 '' 빈 문자열이 된다.
해당 url을 
include하는 polls/urls.py로 전달한다.

그렇게 되면 아까 우리가 설정한 urls.py의 빈문자열에 대한 index 연결이 이해가 될것이다.

그렇다면 테스트 해보자!



(서버 실행)


실행 후, 주소/polls 

를 요청해보자.



(결과)


우리가 원하는 목적을 이루었다.!



(* 참조 - https://docs.djangoproject.com/ko/2.0/intro/tutorial01/)

+ Recent posts