Django

Chapter 5-8 📌 Mini Project - Admin 권한으로 모든 게시글 수정/삭제 가능하게 만들기

Chansman 2025. 5. 8. 10:10

📌 Mini Project - Admin 권한으로 모든 게시글 수정/삭제 가능하게 만들기


🎯 목표

지금까지는 일반 로그인 사용자만 자신의 글을 수정/삭제할 수 있었습니다.
이제는 관리자(Admin) 계정은 모든 글을 관리할 수 있도록 권한을 확장합니다.

이를 위해 다음과 같은 흐름으로 구현합니다:

  1. CBV에서 is_superuser 조건에 따라 쿼리셋 필터링 로직 수정
  2. 템플릿에서 관리자도 버튼이 보이도록 조건 수정
  3. 전체 코드 및 작동 흐름 명확히 정리

✅ 1단계 - CBV 코드 수정 (권한 분기 처리)

# blog/cb_views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import Q
from django.http import Http404, HttpResponseRedirect
from django.urls import reverse_lazy
from django.views.generic import CreateView, DeleteView, DetailView, ListView, UpdateView
from blog.models import Blog

class BlogListView(ListView):
    queryset = Blog.objects.all()
    template_name = 'blog_list.html'
    paginate_by = 10
    ordering = ('-created_at', )

    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

class BlogDetailView(DetailView):
    model = Blog
    template_name = 'blog_detail.html'

class BlogCreateView(LoginRequiredMixin, CreateView):
    model = Blog
    template_name = 'blog_create.html'
    fields = ('category', 'title', 'content')

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

class BlogUpdateView(LoginRequiredMixin, UpdateView):
    model = Blog
    template_name = 'blog_update.html'
    fields = ('category', 'title', 'content')

    def get_queryset(self):
        queryset = super().get_queryset()
        if self.request.user.is_superuser:
            return queryset  # 모든 글 접근 허용
        return queryset.filter(author=self.request.user)  # 본인 글만 수정 가능

class BlogDeleteView(LoginRequiredMixin, DeleteView):
    model = Blog

    def get_queryset(self):
        queryset = super().get_queryset()
        if not self.request.user.is_superuser:
            queryset = queryset.filter(author=self.request.user)
        return queryset

    def get_success_url(self):
        return reverse_lazy('blog:list')

✅ 2단계 - 템플릿 조건문에 Admin 포함

🔄 blog_detail.html

{% if request.user == blog.author or request.user.is_superuser %}
  <div style="text-align: right">
    <a href="{% url 'blog:update' blog.pk %}">수정</a>
    <form id="delete_form" action="{% url 'blog:delete' blog.pk %}" method="POST" style="display: inline">
      {% csrf_token %}
      <button type="button" id="delete_btn">삭제</button>
    </form>
  </div>
{% endif %}

📌 or request.user.is_superuser 조건으로 관리자도 버튼 노출되도록 설정


🔄 작동 흐름 요약 (코드 기반 프로세스 분해 설명)

▶️ ① 게시글 수정/삭제 권한 분기 처리

# CBV 내부
if self.request.user.is_superuser:
    return queryset
return queryset.filter(author=self.request.user)
  • 관리자: 모든 게시글을 조회 및 수정 가능
  • 일반 사용자: 자신이 작성한 게시글만 접근 가능

▶️ ② 템플릿에서 버튼 노출 조건 분기

{% if request.user == blog.author or request.user.is_superuser %}
    <a href="{% url 'blog:update' blog.pk %}">수정</a>
    <form action="{% url 'blog:delete' blog.pk %}" method="POST">
        {% csrf_token %}
        <button type="submit">삭제</button>
    </form>
{% endif %}
  • 작성자 또는 관리자에게만 UI 조작 버튼 노출
  • URL 보호와 UI 보호 모두 적용

▶️ ③ 삭제 버튼 클릭 시 작동 흐름

<script>
  document.querySelector('#delete_btn').addEventListener('click', function() {
    if (confirm('삭제하시겠습니까?')) {
      document.querySelector('#delete_form').submit();
    }
  });
</script>
  • JS 확인창 → 삭제 의도 확인 후 POST 요청으로 폼 전송
  • Django CBV DeleteView에서 처리됨

✅ 정리

  • 관리자 계정은 전체 글 접근 및 수정/삭제 가능
  • CBV의 get_queryset()을 통해 뷰 접근 권한 제어
  • 템플릿에서도 is_superuser 조건 추가로 UI 일관성 확보
  • 자바스크립트 confirm()으로 삭제 UX 보완

💡 이렇게 하면 관리자 페이지 외에도 프론트에서 직접 글 관리가 가능합니다!