대망의 블로그 앱.
우선 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는 전체 페이지 번호임을 기억하도록 하자!
완성된 페이지!
여기서 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을 작동!
즉 get_previous를 통해 이전 Post를 반환하고,
get_absolute_url를 통해 반환된 녀석의 Slug를 인자로 post_deatil url을 작동시킨다!(복잡도 하다!!)
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) 인식도 가능하게 해주자.
완성된 페이지!
현재 first Post의 디테일 화면은 third page에서 href를 통해 접속한 상황이다.
주소창의 url을 보면... blogs/post/first Post의 Slug 형태임을 알 수 있다!!
(get_absolute_url에 slug가 사용된 것)
제일 마지막 페이지(가장 이전/이후 글)에 오면 no page라는 글귀가 뜨도록 했다.
이는 if문 사이 else를 통해 해결!
'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 |