본문 바로가기
source-code/Django

Blogs App

by mattew4483 2020. 12. 31.
728x90
반응형

대망의 블로그 앱.

우선 CRUD 대신 Admin에서 Post를 작성하고, 이를 페이지 개념으로 보여주는 기능을 구현해볼 예정이다.


참고하고 있는 책이 바뀌었기 때문에(파이썬 웹 프로그래밍 실전편) 새로운 프로젝트를 만들었다.

blogsproject 프로젝트를 만들고 그 안에 blogs 앱 생성!

이때 blogsproject의 url와 blogs앱의 url을 분리해주자. (확장성에 있어 더 유용한 방법!)

 

blogsproject.urls.py

include 이용해 야무지게 blogs앱으로 url 연결!

 

이제 blogs앱에서 models, ulrs, views, templates작업을 하면 된다.

 

1. app 생성

2. model 생성

3. urls 작성

4. 각 views & templates 작성

 

이제는 익숙한 순서들!

 

2. model 생성

models.py

으악 엄청 길다! 심지어 밑에 더 있다!

하나하나 당최 무슨 소린지 살펴보자.

 

SlugField라는 녀석을 사용했다.

Slug가 당최 뭔디? 페이지나 포스트를 설명하는 핵심 단어의 집합...이라고 나와있다.

띠요용. 도대체 무슨 소리.

Admin 작성 화면! title을 적었더니 각 단어들이 하이픈으로 자동 연결되어 나타난다!

이러한 단어들의 조합인 Slug를 url에 사용해 검색 엔진에서 더 빨리 페이지를 찾고, 정확성을 높인다고 한다.

unique=True 옵션을 추가해 고유의 값으로 만들어, 특정 포스트를 검색할 때 기본 키 대신 사용되는 것!

(즉, pk대신 사용할 수 있다! 단순한 숫자인 pk는 내용 유추가 어렵지만, slug는 일반 단어들이기 때문에 이해하기 쉽다)

 

DateField를 사용해 시간을 표시해준다.

옵션으로 auto_now_add=True와 auto_now=True를 추가해 각각 post 작성 및 수정 시간을 표시하도록!

 

필드 속성 외에 필요한 파라미터가 있으면 class Meta 를 통해 내부 클래스로 정의해줄 수 있다.

 

db_table을 정의해줌으로서 데이터베이스에 저장되는 테이블의 이름을 지정할 수 있다.

즉 원래 테이블의 이름은 default로 앱명_모델 클래스명인데, 이를 바꿔준 것!

 

ordering을 통해 modify_dt를 기준으로 내림차순 정렬.

즉 생성 및 수정 날짜가 빠른 순서대로 정렬해둔 것이다.

 

get_absolute_url이라는 함수를 사용했다.

이 메소드가 정의된 객체를 지칭하는 url을 반환(reverse함수를 호출)한다는데...

쉽게 해당 객체(여기서는 Post모델일 테다)로 향하는 절대 경로를 반환한다고 생각하면 될 듯!

reverse함수는 (URL 패턴명, URL 스트링에 사용될 파라미터) 를 받으니까...

이 함수를 실행하면, blogs앱의 post_detail함수가 작동되고, 이때 Post 모델의 slug를 함께 넘겨주는 것이다!

 

다음은 get_previous / get_next 함수!

요놈들은 각각 django 내장 함수인 get_previous_by_modify_dt() / get_next_by_modify_dt()를 호출한다.

현재 Post들은 ordering을 통해 생성/수정일 순으로 정렬되어 있다.

따라서 두 함수는 각각 modify_dt 컬럼을 기준으로 최신 / 예전 Post를 반환한다.

 

3. Urls 작성

urls.py

include를 통해 현재 url에는 /blogs/가 붙어있음을 잊지 말자!

app_name을 적어줬는지도 체크! 만약 이를 적어주지 않으면...

NoReverseMatch - not a registered namespace 에러랑 만나게 된다. 으윽.

 

클래스형 뷰를 사용하기 때문에 as_view()를 붙여주는 건 알겠다만... 중간에 이상한 녀석이 끼어있다.

r'^post/(? P <slug>[-\w]+)/$'

\

일단 이는 /blogs/post/슬러그/ <- 이러한 요청을 처리하기 위한 url이다.

 

아까 model에서 우리는 pk대신 Slug를 통해 각 Post들의 고유값을 구별하기로 정했다.

즉 Post의 세부사항을 보여주는 이번 url 요청은 숫자(pk값)가 아닌 단어(Slug)가 들어가는 것!

위 사진처럼 post_detail url의 arguments들은 'f', 'i', 's' 등과 같은 단어들임을 확인할 수 있다.

이를 단순히 post/<slug:slug>/로 적으면..?

<Slug>는 [-a-zA-Z0-p_]+만 인식하기 때문에 한글이 포함된 Slug는 처리하지 못한다고 한다.

 

4. views & templates 작성

views.py

django의 generic 뷰들을 실컷 import 해주자. model도 잊지 말고!

 

1) PostLV view & post_all.html

views.py

첫 화면인 post_all.html은 생성한 Post들을 띄워주는 화면이다. ListView 사용!

model과 template_name을 샥샥 정해주자.

 

ListView가 넘겨주는 context는 default로 object_list란 이름을 갖고 있다.

하지만 context_object_name을 사용하면 마음대로 지정해줄 수 있다는 사실.

 

paginate_by를 지정해줌으로써 django의 페이지 기능을 사용할 수 있게 된다. 

한 페이지에 몇 개를 보여줄지도 정해주자!

 

post_all.html

우선 넘어온 context인 posts를 for문으로 돌려주자.

post들의 title을 클릭하면 해당 post의 세부 페이지로 넘어가도록 할 예정.

 

이를 위해 post.get_absolute_url을 이용한다.

즉 각 post 안에 있는 get_absolute_url을 작동시켜, 해당 post의 절대 경로로 향하게 한 것!

물론 {% url 'blogs:post_detail' post.slug %} 라 적어도 상관없다.

 

각 post들의 modify_dt도 띄워준다.

이때 |date:"N d, Y" 속성을 줌으로써 날짜를 N d, Y 형식으로 출력!

 

post_all.html

view에서 지정해준 paginate_by를 통해 페이지 기능을 사용할 수 있다.

이를 위해 html상에서 이전/다음 페이지로 넘어갈 수 있도록 코드를 작성해줘야 한다.

 

난데없이 page_obj란 녀석이 등장했다.

요놈은 django의 Page 객체가 들어있는 context변수라고 한다. 즉 정해진 값이라는 뜻.

 

아무튼 model에서 지정해준 has_previous를 통해 현재 페이지를 기준으로 이전 페이지가 있는지 확인!

존재할 경우 이전 페이지로 갈 수 있도록 href를 걸어주면 된다.

page_obj의 previous_page_number(이 녀석 역시 정해진 값)는 이전 페이지 번호를 뜻한다!

즉 ?page=이전 페이지 번호라는 url요청을 보내 이전 페이지로 이동하려는 것.

 

그 밑의 녀석들도 비슷하다!

page_obj의 number은 현재 페이지 번호, next_page_number은 다음 페이지 번호를,

paginator.num_pages는 전체 페이지 번호임을 기억하도록 하자!

 

post_all.html

완성된 페이지!

여기서 Nextpage를 클릭하면... 쨔잔.

 

이렇게 다음 페이지로 이동하게 된다.

여기서 url을 유의해서 보도록 하자! (blogs/?page=페이지 번호 형태)

 

2) PostDV view & post_detail.html

views.py

각 Post들의 세부사항을 보여줄 예정. DetailView를 사용하자.

 

post_detail.html

detail 페이지에서도 다음 Post의 detail 페이지로 넘어갈 수 있게 할 예정이다.

 

view에서 넘겨준 object들 중 get_previous, 즉 modify_dt 칼럼을 기준으로 이전 Post가 있으면..!

{{object.get_previous.get_absolute_url}} <- 모델의 get_previous의 get_absolute_url을 작동!

models.py

즉 get_previous를 통해 이전 Post를 반환하고,

get_absolute_url를 통해 반환된 녀석의 Slug를 인자로 post_deatil url을 작동시킨다!(복잡도 하다!!)

post_detail.html

post_detail에 들어오면 이렇게 페이지 이동이 가능해진다.

중간 이모지는 구분을 위해 임의로 넣은 것

이때 href의 글귀들은? 각 Post들의 Slug 값들!! 

(href의 value로 {{object.get_previous}}를 지정했으니까!)

클릭하면 각각 이전 / 이후 Post의 detail 페이지로 잘 이동함을 확인할 수 있다.

 

나머지 녀석들!

 

{{ object.modify_dt }}를 통해 각 object들의 수정일을 띄워준다.

|date:"j F Y" 속성을 줌으로써 j F Y 형식으로 날짜 표시!

 

{{ object.content }}를 통해 각 object들의 content를 띄워주고...

linebreaks속성을 통해 엔터(새로운 line) 인식도 가능하게 해주자.

post_detail.html

완성된 페이지! 

현재 first Post의 디테일 화면은 third page에서 href를 통해 접속한 상황이다.

주소창의 url을 보면... blogs/post/first Post의 Slug 형태임을 알 수 있다!!

(get_absolute_url에 slug가 사용된 것)

 

제일 마지막 페이지(가장 이전/이후 글)에 오면 no page라는 글귀가 뜨도록 했다.

이는 if문 사이 else를 통해 해결!

728x90
반응형

'source-code > Django' 카테고리의 다른 글

Blogs App _ 댓글 기능  (0) 2021.01.02
Blogs App _ tag 기능  (0) 2021.01.01
Books App _ log 만들기  (0) 2020.12.30
Books App _ home 만들기  (0) 2020.12.30
Books App _ Template 상속하기  (0) 2020.12.30