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

IkSun·2023년 7월 3일

작정하고 장고

목록 보기
42/46

구독 기능, 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 를 넣어서 전송
<!-- /projectapp/templates/projectapp/detail.html -->
{% extends 'base.html' %}

{% block content %}

  <div>
    <!-- 프로젝트 상세정볼 보여주는 부분 -->
    <div style="text-align: center; max-width: 500px; margin: 4rem auto 1.5rem auto;"> <!-- margin 4개로 나눠 쓰기 (위오아왼) -->
      <img src="{{ target_project.image.url }}" alt=""
      style="height: 12rem; width: 12rem; border-radius: 20rem; margin-bottom: 2rem; object-fit: cover;">
      <h2 style="font-family: 'NanumSquareB'">
        {{ target_project.title }}
      </h2>
      <h5>
        {{ target_project.description}}
      </h5>
    </div>

    <!-- 구독 버튼 -->
    <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>


  </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

profile
공부한 것 기록용

0개의 댓글