[Django] Pinterest 만들기 (9)

17355 단어 djangodjango

RedirectView를 통한 SubscribeApp 시작

subscribeapp을 만들고 settings.py와 urls.py를 설정해준다

다음과 같이 models.py를 작성해준다.

from django.db import models
from django.contrib.auth.models import User

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:
        unique_together = ('user', 'project')

user와 그 유저가 가지는 project가 1개가 되도록 그 쌍을 만들어야한다. 따라서 user와 project를 만들어주고 Meta 클래스를 이용해서 그 구독정보를 하나의 쌍으로 만들어준다.

views.py도 작성해준다.

from django.shortcuts import render

# Create your views here.
from django.urls import reverse
from django.views.generic import RedirectView
from django.utils.decoratos import method_decorator

from projectapp.models import Project

from subscribeapp.view import SubscriptionView
from subscribeapp.models import Subscription


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

    def get_redirect_url(self, *args, **kwargs):
        return reverse('projectapp:detail', kwargs={'pk': self.request.GET.get('project_pk')})

    def get(self, request, *args, **kwargs):
        project = get_object_or_404(
            Project, pk=self.request.GET.get('project_pk'))
        user = self.request.user

        subscription = Subscription.objects.filter(user=user, project=project)

        if subscription.exists():
            subscription.delete()
        else:
            Subscription(user=user, project=project).save()

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

projectapp/detail에서 구독을 누르도록 하므로 get_redirect_url 함수를 다음과 같이 적어주고 pk값을 넘겨준다.

그리고 project와 user 정보를 취합해서 구독정보를 찾아준다.

그리고 projectapp을 건드려준다.
detail.html 가운데에 구독버튼을 추가해준다.

<div class="text-center mb-5">
    {% if user.is_authenticated %}
        {% if not subscription %}
        <a href="{% url 'subscribeapp:subscribe' %}?project_pk={{ target_project.pk }}" class="btn btn-primary rounded-pill px-4">
            Subscribe
        </a>
        {% else %}
        <a href="{% url 'subscribeapp:subscribe' %}?project_pk={{ target_project.pk }}" class="btn btn-dark rounded-pill px-4">
            Unsubscribe
        </a>

        {% endif %}
    {% endif %}
</div>

그리고 projectdetailview 내에 있는 get_context_data 함수를 다음과 같이 수정한다

def get_context_data(self, **kwargs):
        project = self.object
        user = self.request.user
        if user.is_authenticated:
            subscription = Subscription.objects.filter(
                user=user, project=project)

        object_list = Article.objects.filter(project=self.get_object())
        return super(ProjectDetailView, self).get_context_data(object_list=object_list, subscription=subscription, **kwargs)

project와 user에 대해서 구독정보가 있는지 없는지에 대한 코드 3줄을 추가해준다.

실행해보면 구독버튼을 눌렀을 때 잘 변경된다.

Field Lookup을 사용한 구독 페이지 구현

  1. 유저가 구독하고 있는 프로젝트들
  2. 프로젝트들 안에 있는 게시물들

이 2가지를 구현하려고 한다. 그동안 접근했던 방식은 Articles.objects.filter(pk=xxx, user=xxx)와 같은 형식이었다. 이것은 and function이다. 하지만 1,2번을 모두 가져오려면 or function을 사용해야한다. 그래서 지금까지와는 다르게 Articles.objects.filter(project_in=projects) 이런식으로 사용할 것이다.

views.py에 listview를 추가한다

class SubscriptionListView(ListView):
    model = Article
    context_object_name = 'article_list'
    template_name = 'subscribeapp/list.html'
    paginate_by = 5

    def get_queryset(self):
        project = Subscription.objects.filter(
            user=self.request.user).values_list('project')
        article_list = Article.objects.filter(project__in=project)
        return article_list

get_queryset 함수를 이용해서 우리가 가져오려는 정보들의 조건을 바꿔줄 수 있다.
우선 구독하고 있는 프로젝트들을 찾는다. values_list는 값들을 가져와 리스트화 시킨다라고 생각하면 된다.

subscribeapp 내에 template을 만들고 list.html을 만들어준다

{% extends 'base.html' %}

{% block content %}

    <div>
        {% include 'snippets/list_fragment.html' with article_list=article_list %}
    </div>

{% endblock %}

header에 구독페이지로 들어갈 링크를 추가해준다

<a href="{% url 'projectapp:list' %}" class="pinterest_header_nav">
    <span>Projects</span>
</a>

좋은 웹페이지 즐겨찾기