FBV (Function Based View)와 CBV (Class Based View)
210724
FBV (Function Based View)로 블로그 리스트 페이지 만들기
기본적으로 프로젝트 폴더에 있는 urls.py
에는 admin/
만 등록되어 있다. 따라서 다음과 같이 127.0.0.1/blog
주소로 들어가면 404 오류가 난다.

urls.py
에 있는 urlpatterns
은 이정표의 의미. 나아갈 수 있는 링크들을 의미한다. 여기에 blog/
를 추가해주면 된다.
urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('blog/', include('blog.urls')),
path('admin/', admin.site.urls),
]
이 때 include 라는 함수를 import 해줘야 한다
blog 앱 폴더에는 아직 urls 라는 파일이 없다. 따라서 이를 추가해줘야 한다.
blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
]
이 때
views.index
를 호출하므로views.py
에서index
함수를 선언해줘야 한다.지금처럼 하는 방법이 FBV 방법
blog/views.py
from django.shortcuts import render
def index(request):
return render(
request,
'blog/index.html',
)
blog의 index.html을 가지고 렌더링 하라는 뜻
따라서 index.html이 또 필요하다.
templates 라는 폴더 안에, blog 라는 폴더 안에 index.html을 만든다
templates/blog/index.html
앱의 독립성을 위해 이렇게 작업하며 추후에 추가 설명
blog/templates/blog/index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Blog</title>
</head>
<body>
<h1>blog</h1>
</body>
</html>

지금까지 한 작업은 클라이언트에서 View로 요청을하고 View가 템플릿을 렌더링 한 후 응답을 준 과정이다.
이제 Model에서 DB로 쿼리를 날린 후 데이터를 얻어서 응답을 주는 과정을 해보려고 한다.
blog/views.py
from django.shortcuts import render
from .models import Post
def index(request):
posts = Post.objects.all()
return render(
request,
'blog/index.html',
{
'posts' : posts,
},
)
렌더링의 리턴값으로 posts 라는 dictionary를 추가했다.
이 posts는 models.py에 있는 post class이다.
지금부터의 파일들은 특별한 명시가 없으면 모두 blog 앱 내부에 있는 파일이다.
index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Blog</title>
</head>
<body>
<h1>blog</h1>
{% for p in posts %}
<h3>{{ p }}</h3>
{% endfor %}
</body>
</html>
10-12
html에서 동적언어를 쓸 수 있게끔 장고에서 지원한다.
for문을 시작할 때와 끝날 때 {% %} 를 써준다.
posts는
views.py
에 있는 dictionary 값으로 'posts' key에 대한 value 값들을 하나씩 <h3> 형태로 작성되게 한다.

이 때 어떻게 p 를 부르기만 해도 db에 저장된 내용이 다 뜰까?
이유는
models.py
에 정의되어있는 __str__ 함수 때문
models.py
def __str__(self):
return f"{self.pk} {self.title}"
좀 더 추가해보자.
index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Blog</title>
</head>
<body>
<h1>blog</h1>
{% for p in posts %}
<hr/>
<h3>{{ p }}</h3>
<h4>{{ p.create_at }}</h4>
<p> {{ p.context }}</p>
{% endfor %}
</body>
</html>

또한, posts의 값들을 특정 테이블값으로 정렬할 수 있다.
views.py
# pk 순
posts = Post.objects.all().order_by('pk')
# pk 역순
posts = Post.objects.all().order_by('-pk')
여기서 objects.all()은 쿼리문이라고 생각하면 된다.
FBV (Function Based View)로 블로그 상세 페이지 만들기
blog 페이지에서 게시글을 눌렀을 때 새로운 페이지로 이동하는 과정을 구성할 것임
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('<int:pk>/', views.single_post_page)
path('', views.index),
]
<> 안에는 자료형을 넣을 수 있으며 pk가 정수로 오기 때문에 다음과 같이 가능
views.py
에single_post_page
함수를 추가할 것임
views.py
def single_post_page(request, pk):
post = Post.objects.get(pk=pk)
return render(
request,
'blog/single_page.html',
{
'post': post,
}
)
single_page.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>{{ post.title }} - Blog</title>
</head>
<body>
<nav>
<a href="/blog/">Blog</a>
</nav>
<h1>{{ post.title }}</h1>
<h4>{{ post.created_at }}</h4>
<p>{{ post.content }}</p>
<p>여기에 댓글이 들어올 수 있겠죠?</p>
</body>
</html>

여기서 블로그를 누르면 모든 /blog 로 이동한다.

index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Blog</title>
</head>
<body>
<h1>blog</h1>
{% for p in posts %}
<hr/>
<h3>><a href="{{ p.get_absolute_url }}">{{ p }}</a></h3>
<h4>{{ p.create_at }}</h4>
<p> {{ p.context }}</p>
{% endfor %}
</body>
</html>
여기서
p.get_absolute_url
를 호출할 수 있다. 이것은model.py
에서 정의해줘야 하는 함수이지만 장고에서 제공해주는 기능이다.장고에서 제공하는 기능을 정의해주면 된다는 뜻
models.py
def get_absolute_url(self):
return f'/blog/{self.pk}'

각 포스트에서 /blog로 이동할 수 있으며 admin 페이지에서도 view on site 기능이 추가되었다.
FBV로 대문 페이지 자기소개페이지 만들기
127.0.0.1/8000 에서 blog나 admin을 입력하지 않으면 에러가 발생한다. 대문 페이지도 마련해주자.
urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('blog/', include('blog.urls')),
path('admin/', admin.site.urls),
path('', include('single_pages.urls'))
]
single_pages/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.landing),
]
single_pages/views.py
from django.shortcuts import render
def landing(request):
return render(
request,
'single_pages/landing.html',
)
single_pages/templates/single_pages/landing.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>상민이의 웹사이트</title>
</head>
<body>
<nav>
<a href="/blog/">Blog</a>
<a href="/about_me/">About me</a>
</nav>
<h1>안녕하세요. 전상민입니다.</h1>
<h2>대문 페이지</h2>
<h3>개발중...</h3>
</body>
</html>

CBV로 블로그 포스트 목록 페이지 만들기
장고에서 이러한 블로그 페이지들을 클래스로 제공하고 있다.
blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('<int:pk>/', views.single_post_page),
path('', views.PostList.as_view())
# path('', views.index),
]
blog/views.py
from django.shortcuts import render
from django.views.generic import ListView
from .models import Post
class PostList(ListView):
model = Post
template_name = "blog/index.html"
# def index(request):
# posts = Post.objects.all().order_by('pk')
# return render(
# request,
# 'blog/index.html',
# {
# 'posts' : posts,
# },
# )
이 때 서버를 실행해보면,

아무것도 뜨지 않는다. 이는,
index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Blog</title>
</head>
<body>
<h1>blog</h1>
{% for p in posts %}
<hr/>
<h3>><a href="{{ p.get_absolute_url }}">{{ p }}</a></h3>
<h4>{{ p.create_at }}</h4>
<p> {{ p.context }}</p>
{% endfor %}
</body>
</html>
반복문에서 posts에 해당하는 dictionary가 없기 때문이다. 기본적으로 장고에서 제공하는 CBV는 dictionary 변수를 post_list
로 정의한다. 따라서 이렇게 수정해주면 된다.
{% for p in post_list %}

또한, views.py 에서 template_name을 선언해주지 않고 template 파일 이름을 post_list
로 변경해주면 된다.
또, 순서도 정해줄 수 있다.
views.py
class PostList(ListView):
model = Post
ordering = '-pk'
CBV로 블로그 포스트 상세 페이지 만들기
마찬가지로 single_page도 클래스로 선언 가능하다.
views.py
from django.shortcuts import render
from django.views.generic import ListView, DetailView
from .models import Post
class PostDetail(DetailView):
model = Post
# def single_post_page(request, pk):
# post = Post.objects.get(pk=pk)
# return render(
# request,
# 'blog/single_page.html',
# {
# 'post': post,
# }
# )
그리고 템플릿 파일 이름을 post_detail.html
로 변경한다.
마지막으로, url도 변경해주면 끝.
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('<int:pk>/', views.PostDetail.as_view()),
# path('<int:pk>/', views.single_post_page),
path('', views.PostList.as_view())
# path('', views.index),
]
장고에서는 CBV로 제공하는 기능이 많기 때문에 편리하게 이용할 수 있고 이것을 직접 구현하기는 소모적이기 때문에 CBV를 사용하는 것을 권장한다!
Last updated
Was this helpful?