2025/11/11 Django - 5

김기훈·2025년 11월 11일

TIL

목록 보기
52/194

오늘 학습 내용

[블로그] CBV 활용해 상세페이지 만들기

CBV(Class Based View)

Class-Based Views 공식문서
generic view

  • Python 클래스로 뷰를 정의하는 방식
    • CBV는 Django의 뷰에 대한 다양한 기능을 더 구조적으로 사용할 수 있게 해줌
  • 장점
    • 재사용성: CBV는 상속과 믹스인(Mixins)을 통해 코드의 재사용성을 높일 수 있음
    • 구조화된 코드: 뷰 로직을 클래스 메서드로 나누어 복잡한 뷰를 더 구조적으로 관리할 수 있음
      • 잘 쓸경우 코드가 짧아짐 / 구조가 나누어져 있어서 코드 가독성 증가
    • 확장성: 다양한 클래스 기반 뷰
      • (ex. ListViewDetailViewCreateView)를 사용해 일반적인 패턴을 쉽게 구현
  • 단점
    • 배워야 하는게 많아짐
    • 잘 모르고 사용할 경우 너무 어렵고 복잡

TemplateView

  • 지금까지 했던 방법

  • 한줄로 처리 가능

  • 이전보다 좀더 간결하게 변경

  • 어바웃 페이지로 이동하는 리다이렉트 뷰(기본 방법 / 익명함수 lambda를 사용하는 방법)

  • path('redirect/', RedirectView.as_view(pattern_name='about'), name='redirect')

    • http://127.0.0.1:8000/redirect/ pattern_name과 동일 이름으로 이동
    • redirect / redirecr2 둘다 about 로 이동함

TestView

  • 이전까지는 POST, GET 등 호출 유형 별로 if~else문을 써야했음
    • 지금부터는 CBV를 활용해 함수만으로 구현이 가능

블로그 List 페이지를 CBV로 바꾸기

# blog/cb_views.py

from django.db.models import Q
from django.views.generic import ListView

from blog.models import Blog

class BlogListView(ListView): # ListView 상속
    queryset = Blog.objects.all()
    template_name = 'blog_list.html' # 렌더링
    paginate_by = 10 # 페이지네이션
    ordering = ('-created_at', ) # 역정렬

		# ListView 내장 함수
		# 검색기능
    def get_queryset(self):
        queryset = super().get_queryset()

        q = self.request.GET.get('q')
        if q:
            queryset = queryset.filter(
                Q(title__icontains=q) |
                Q(content__icontains=q)
            )
        return queryset
  • model = Blog 이렇게 넣으면 무조건 Blog.objects.all() 로 가져옴

  • 페이지네이션 / 역정렬 추가

    • queryset = Blog.objects.all().order_by('-created_at') 이렇게 안하고
    • 따로 queryset = Blog.objects.all() / ordering = ('-created_at') 가능
  • 검색기능 추가


블로그 Detail 페이지를 CBV로 바꾸기

  • pk를 기준으로 int값을 가져오기 때문에 urls에서 pk로 잡아야 함
  • object.content로 해도 cbv에서는 작동 하지만 fbv에서는 작동 X
## 커스터마이징 부분

class BlogDetailView(DetailView):
 
    """
    1. 이 속성은 URL에서 데이터를 찾을때 사용할 키 이름을 바꿔주는 것
    보통 Django는 pk를 기준으로 데이터를 찾는데, 만약 URL 에서 id라는 이름을 쓰고 싶으면 이걸로 바꿔야함
    URL이 blog/5/ 라면 pk를 쓰고, URL이 blog/<int:id>/라면 id를 씀    
    """
		pk_url_kwarg = 'id'
		
		
		"""
    2. get_queryset 메서드는 어떤 데이터를 보여줄지 결정하는 것으로 데이터전체에서 필터링하는 느낌
    블로그 글이 100개 있는데, id=50이하인 글만 보여주고 싶을 때 사용
    queryset = super().get_queryset()        # 전체 데이터 가져오기
    return queryset.filter(id__lte=50)       # 그 중에서 id가 50 이하인 것만 골라내기
    결과는 50번째 글까지만 보여줌
    """
		def get_queryset(self):
			   queryset = super().get_queryset()
			   return queryset.filter(id__lte=50)
	       
			
		"""
    3. get_object 메서드는 URL에서 특정 글(데이터) 하나를 가져오는 방법을 바꾸는것
    지금은 별로 바뀌는게 없지만, 나중에 더 복잡한 조건(ex.이 글을 작성한 사람만 볼 수 있다) 같은 걸 추가가능
    object = super().get_object()        # 기본 방식으로 글 하나 가져오기
    object = self.model.objects.get(pk=self.kwargs.get('pk'))           # 다시 글 찾기
    self.model.objects.get()은 pk = 5인 데이터를 데이터베이스에서 직접 가져오는 방법
    self.kwargs.get('pk') 는 URL에서 pk값을 가져옴
    결과는 그냥 글 하나 가져오는 기본 방식이랑 거의 똑같지만, 나중에 수정할 준비를 해둔 것
    """
		def get_object(self, queryset=None):
		    object = super().get_object()
		    object = self.model.objects.get(pk=self.kwargs.get('pk'))
		
		    return object


		"""
    4. 템플릿 추가로 데이터를 전달하는 것으로 템플릿에서 사용할 수 있는 변수를 더 만드는 것
    템플릿에 CBV라는 텍스트를 표시하고 싶을때 쓸 수 있음
    결과는 템플릿에서 {{ test }} 를 쓰면 CBV라는 값이 나옴
    context = super().get_context_data(**kwargs)        # 기본 데이터 가져오기
    context['test'] = 'CBV'                              # 추가로 test라는 이름으로 'CBV' 넣기
    """
    def get_context_data(self, **kwargs):
		    context = super().get_context_data(**kwargs)
		    context['test'] = 'CBV'
		    return context

블로그 Create 페이지를 CBV로 바꾸기

  • LoginRequiredMixin

    • FBV에서는 @login_required 사용
    • 사용자가 로그인을 해야만 이 뷰에 접근할 수 있도록 함
    • 만약 로그인을 하지 않은 사용자가 접근하려고 하면, 로그인 페이지로 리디렉션
  • CreateView

    • Django에서 제공하는 제네릭 뷰로, 새로운 객체를 생성하는 폼을 처리하는 데 사용
  • 블로그 작성 페이지까지는 들어갔지만 생성이 안되는 오류 해결

  • 변경가능한 pk가 필요할 경우

    • 앞선 코드는 블로그를 작성하고 생성하면 바로 http://127.0.0.1:8000/cb/ 로 가짐
      • 바로 리스트로 간다건다 하는 정적인 url이 필요하면 success_url = 사용
    • 함수를 추가한 코드는 http://127.0.0.1:8000/cb/175/ 작성한 글에 대한 상세페이지로 가짐
      - 디테일 페이지로 가야해서 디테일 pk가 필요하다면 def get_success_url(self) 사용

추가

# 1
    def form_valid(self, form): 
        self.object = form.save(commit=False)
        self.object.author = self.request.user
        self.object.save()
        return HttpResponseRedirect(self.get_success_url())
# 2        
    def form_valid(self, form): 
        blog = form.save(commit=False)
        blog.author = self.request.user
        blog.save()
        self.object = blog 
        return HttpResponseRedirect(self.get_success_url())
        
  • 둘다 가능

블로그 Update 페이지를 CBV로 바꾸기

  • BlogUpdateView 클래스의 get_success_url 함수 대신
    • 모델에 get_absolute_url 함수를 사용하여 객체의 고유 URL을 반환
  • models.py에 이렇게 해놓으면 cb_views.py에서 success_url이 없을경우 자동으로
    • models.py의 get_absolute_url을 찾아서 이용 함
      • create에서도 success_url 안해도 됨

  • author=self.request.user
    • 본인이 작성한 글이 아닐 경우 404 반환

추가

  • 유저가 같은 유저가 맞는지 확인하는 코드
# 1
    def get_queryset(self):
        queryset = super().get_queryset()
        return queryset.filter(author=self.request.user)
   
# 2   
    def get_object(self, queryset = None):
        self.object = super().get_object(queryset)
        
        if self.object.author != self.request.user:
            raise Http404
        return self.object
  • 두가지 방법 전부 가능

블로그 Delete 페이지를 CBV로 바꾸기

삭제 버튼을 눌렀을 때, 팝업창으로 한 번 더 확인하도록


URL include

  • 공통된 url주소를 통해 관리를 용이하게 할 수 있음(ex. product/ , product/123 )
    • blog에서 urls.py 파일을 생성하고 blog와 관련된 url을 관리
      • fbv_urls.py 파일도 생성해서 관리

실습

  • include 전 {% url 'blog_list' %} / include 후 {% url 'blog:list' %}
    • blog 는 app_name

Admin 권한 처리

  • Admin 계정으로 로그인 한 경우 일반페이지에서도 글 관리가 가능하도록

  • user2 가 작성한 글을 admin이 수정이나 삭제가 불가


카테고리

  • 카테고리가 안잡힌 것들도 있어서 업데이트 해보기
    • null이 아니라 공백으로 잡혀있어서 isnull=True 안통한 것

  • 수정 및 업데이트에 카테고리 추가

새롭게 알게된 내용

  • Command 누르고 클릭해보면 함수의 사용법을 알 수 있음

  • pycharm 에서 cmd + R

  • pycharm 에서 cmd+, -> 키맵 -> caret

    • 여러개 한번에 드래그 같은거 가능
  • cmd + shift + F = 전체검색

어려운 내용(추가 학습 필요)

  • 블로그 Detail 페이지를 CBV로 바꾸기
  • include

오늘 발생한 문제(발생 했다면)

  • 문제 1. BlogCreateView 를 사용하면서 urls까지 해놓고 연결해봤는데 연결 안됨

  • 원인 : 에러 페이지에서 말했듯 필드가 fields 가 필요

  • 해결

profile
안녕하세요.

0개의 댓글