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


구독을 할떈 따로 구독 정보를 입력하는 것이 아니기 떄문에 form 으로 입력창을 보여줄만한 그런 중간 과정이 필요가 없음.
따라서 바로 요청을 받자마자 처리할 것 처리하고, redirect 하기 위해서 RedirectView 를 만들어볼 것.
from django.urls import path
app_name = 'subscribeapp'
urlpatterns = [
]
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)
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')
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)


<!-- /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 %}
from django.urls import path
from subscribeapp.views import SubscriptionView
app_name = 'subscribeapp'
urlpatterns = [
path('subscribe/', SubscriptionView.as_view(), name='subscribe')
]

구독 버튼이 생성됨. 하지만 구독 버튼을 눌렀을때의 어떠한 변화도 없음. -> projectapp 의 detailview 수정
지금 접속해 있는 유저가 이 게시판(project) 에 대한 구독 정보가 있는지 없는지를 확인하는 작업이 필요함

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


