작정하고 Django 42강 - RedirectView를 통한 Subscribeapp 시작

_·2024년 1월 7일

작정하고 Django 강의

목록 보기
41/44

구독 기능, subscribe 기능을 RedirectView 라는 것을 만들어서 구현.

구독을 할떈 따로 구독 정보를 입력하는 것이 아니기 떄문에 form 으로 입력창을 보여줄만한 그런 중간 과정이 필요가 없음.

따라서 바로 요청을 받자마자 처리할 것 처리하고, redirect 하기 위해서 RedirectView 를 만들어볼 것.

app 시작
python manage.py startapp subscribeapp
settings.py -> subscribeapp 등록
urls.py -> path('subscribe/', include('subscribeapp.urls'))
subscribeapp -> urls.py 생성
from django.urls import path

app_name = 'subscribeapp'

urlpatterns = [

]
views.py 작성
views.py 작성
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.views.generic import RedirectView

Create your views here.

로그인을 해야지 구독을 할 수 있도록 하기, 숨길건 없으므로 get 방식

@method_decorator(login_required, 'get')
class SubscriptionView(RedirectView):

def get_redirect_url(self, *args, **kwargs):

    # detail 안아서 구독 버튼을 누를 수 있도록 하기 위해 되 돌아갈 곳은 projectapp 에서 detail 페이지
    # project_pk 를 get 방식으로 보내어 해당 'pk' 를 가지고 있는 detail 페이지로 되돌아가기
    return reverse('projectapp:detail', kwargs={'pk' : self.request.GET.get('project_pk')})

def get(self, request, *args, **kwargs):
    
    return super(SubscriptionView, self).get(request, *args, **kwargs)

모델 작성
view 내용을 채우기 전에 model 작성 후 migration 작업
from django.contrib.auth.models import User
from django.db import models

from projectapp.models import Project

Create your models here.

class Subscription(models.Model):

# 유저 연결
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='subscription')
# 프로젝트 연결
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='subscription')

class Meta: # Meta 정보로 넘겨주기
    # 어떤 유저와 어떤 프로젝트 그 쌍이 가지는 구독 정보가 단 하나가 되도록 설정.
    unique_together = ('user', 'project')

구독 기능 구현
이후 subscribeapp/views.py 마저 작성하기
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.views.generic import RedirectView

from projectapp.models import Project
from subscribeapp.models import Subscription

Create your views here.

로그인을 해야지 구독을 할 수 있도록 하기, 숨길건 없으므로 get 방식

@method_decorator(login_required, 'get')
class SubscriptionView(RedirectView):

def get_redirect_url(self, *args, **kwargs):

    # detail 안아서 구독 버튼을 누를 수 있도록 하기 위해 되 돌아갈 곳은 projectapp 에서 detail 페이지
    # project_pk 를 get 방식으로 보내어 해당 'pk' 를 가지고 있는 detail 페이지로 되돌아가기
    return reverse('projectapp:detail', kwargs={'pk' : self.request.GET.get('project_pk')})

def get(self, request, *args, **kwargs):
    # 프로젝트와 유저정보를 취합하기 부분 추가 (get_object_or_404 라는 단축함수 사용하여 예외처리)
    # project_pk 를 가지고 있는 Project 를 찾는데,
    # 그게 만약 없다면(없는 프로젝트에 대한 구독의 경우) '페이지를 찾을 수 없음' 을 되돌려주도록
    project = get_object_or_404(Project, pk=self.request.GET.get('project_pk'))
    user = self.request.user   # user 찾기


    # user, project 가 각각 우리가 앞서 찾은 user, project 인 구독정보를 찾기
    subscription = Subscription.objects.filter(user=user,
                                               project=project)
    if subscription.exists():   # 구독 정보가 존재한다면, 지우기
        subscription.delete()
    else: # 구독 정보가 존재하지 않는다면
        Subscription(user=user, project=project).save() # -> 앞서 찾은 user,project 로 구독정보를 만들어야함.
        # 대문자 S



    return super(SubscriptionView, self).get(request, *args, **kwargs)

구독 버튼 만들어주기

버튼 자체는 로그인을 한 사람들에게만 보이도록 하기 위해 if 문 작성
우리가 만들었던 'subscribeapp:subscribe' 로 향하는 url 을 만들어 주고
뷰단에서 get 방식으로 project_pk 라는 데이터를 넘겨주기 떄문에

추가로 url 뒤에 get 방식으로 project_pk 에다가 현재 target_project 의 pk 를 넣어서 전송

{% extends 'base.html' %}

{% block content %}

{{ target_project.title }}

{{ target_project.description}}
<!-- 구독 버튼 -->
<div class="text-center mb-5" >
  {% if user.is_authenticated %}
  <a href="{% url 'subscribeapp:subscribe' %}?project_pk={{ target_project.pk }}" 
     class="btn btn=primary rounded-pill px-3">   <!-- 버튼 스타일 바꾸기-->>
    Subscribe
  </a>
  {% endif %}
</div>

<!-- 게시글 보여주기 부분 -->
</div>
  {% include 'snippets/list_fragment.html' with article_list=object_list %}
<div>

{% endblock %}
SubscribeView 작성 완료 후 subscribeapp 안의 url 등록
from django.urls import path

from subscribeapp.views import SubscriptionView

app_name = 'subscribeapp'

urlpatterns = [
path('subscribe/', SubscriptionView.as_view(), name='subscribe')
]

구독 버튼이 생성됨. 하지만 구독 버튼을 눌렀을때의 어떠한 변화도 없음. -> projectapp 의 detailview 수정

지금 접속해 있는 유저가 이 게시판(project) 에 대한 구독 정보가 있는지 없는지를 확인하는 작업이 필요함

/projectapp/views.py 수정

class ProjectDetailView(DetailView, MultipleObjectMixin):
model = Project
context_object_name = 'target_project'
template_name = 'projectapp/detail.html'

paginate_by = 25

def get_context_data(self, **kwargs):
    project = self.object   # object : 현재 project 페이지
    user = self.request.user

    # 유저가 로그인을 했는지 안했는지 확인
    if user.is_authenticated: # 유저가 접속이 되있다면, usr 와 project 가 각각 user, project 인 구독정보를 찾고
        subscription = Subscription.objects.filter(user=user, project=project)
    # 유저가 접속되어있지 않는다면 구독 버튼 자체가 없기 떄문에 else 구문은 생략

    object_list = Article.objects.filter(project=self.get_object())
    # 최종적으로 템플릿으로 넘어갈때는 context_data 안에다가 구독 정보를 우리가 찾은 'subsriptiom' 으로 대체
    # 이런식으로 구독 정보가 있는지 없는지 확인
    return super(ProjectDetailView, self).get_context_data(object_list=object_list,
                                                           subscription=subscription,
                                                           **kwargs)

template 수정
/projectapp/templates/projectapp/detail.html 에서 사용자 인증과정을 통해 구독을 할때 안할때를 구분하여, '구독' '구독하지 않음' 버튼을 따로 설정.

<div class="text-center mb-5"> <!-- mb-5 : margin-bottom -->
  {% if user.is_authenticated %}
    {% if not subscription %} <!-- 구독이 아닐떄 구독 버튼을 보여주기-->
    <a href="{% url 'subscribeapp:subscribe' %}?project_pk={{ target_project.pk }}"
       class="btn btn-primary rounded-pill px-3">   <!-- 버튼 스타일 바꾸기-->
      Subscribe
    </a>
    {% else %} <!-- 구독이 아닐때, 구독 취소 버튼-->
    <a href="{% url 'subscribeapp:subscribe' %}?project_pk={{ target_project.pk }}"
       class="btn btn-dark rounded-pill px-3">   <!-- 버튼 스타일 바꾸기-->
      Unsubscribe
    </a>
    {% endif %}
  {% endif %}
</div>

결과
구독 후

구독취소 후

commit

0개의 댓글