Q&A

책을 따라하다가 막히는 부분이 있나요?
질문을 남겨주세요.

Post 작성 시 태그를 달면서 다음과 같은 에러가 발생했습니다.

1 year, 11 months ago

Gon Gon

관리자 페이지(admin) 페이지에서 작성한 태그는 글 작성이 되는데 관리자 페이지에 작성되어 있는 태그를 사용하지 않고 태그를 달아 블로그 게시물을 올리면 다음과 같은 에러가 나옵니다. 에러 구문은 다음 라인에서 발생했다고 합니다. 어디서 발생한 오류이며 해결 방안이 어떻게 되는지 물어보고 싶습니다.

views.py에서 발생했습니다.


views.py의 소스코드입니다.

# CBV 방식으로 변경하기

# from django.shortcuts import render

from django.views.generic import ListView, DetailView, CreateView, UpdateView    # Detail을 불러오겠음

# django -> views -> generic 안의 CreateView를 불러오겠음.


# 로그인 관련해서 django에서 지원해주는 라이브러리

# 로그인되어있을때만 보여줌

from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin

# UserPassesTestMixin : 스태프


from .models import Post, Category, Tag, Comment


from django.shortcuts import render, redirect, get_object_or_404


from django.core.exceptions import PermissionDenied


from django.utils.text import slugify


from .forms import CommentForm


from django.db.models import Q


# --------------------------------------------------------------------------------------------------------------


class CommentUpdate(LoginRequiredMixin, UpdateView):

    model = Comment

    form_class = CommentForm

    

    def dispatch(self, request, *args, **kwargs):

        if request.user.is_authenticated and request.user == self.get_object().author:

            return super(CommentUpdate, self).dispatch(request, *args, **kwargs)

            

        else:

            raise PermissionDenied


class PostUpdate(LoginRequiredMixin, UpdateView):

    model = Post

    fields = ['title', 'hook_text', 'content', 'head_image', 'file_upload', 'category', 'tags']

    

    # _form.html

    template_name = 'blog/post_update_form.html'

    # 원하는데로 보낼 수 있게 하는 방법

    

    def get_context_data(self, **kwargs):

        context = super(PostUpdate, self).get_context_data()

        if self.object.tags.exists():

            tags_str_list = list()

            for t in self.object.tags.all():

                tags_str_list.append(t.name)

            context['tags_str_default'] = ';'.join(tags_str_list)

        return context


    def form_valid(self, form):

        response = super(PostUpdate, self).form_valid(form)

        self.object.tags.clear()

            

        tags_str = self.request.POST.get('tags_str')  # POST : post 방식으로 매서드가 온 것

        if tags_str:

            tags_str = tags_str.strip()  # strip() : 공백 제거

            tags_str = tags_str.replace(',', ';')  # ,를 ;로 변경하기

            tags_list = tags_str.split(';')  # ;을 기준으로 전부 나눠짐

                

            for t in tags_list:

                t = t.strip()

                tag, is_tag_created = Tag.objects.get_or_create(name=t)

                # 같은 이름을 갖는 태그가 없으면 생성하고, 있으면 그대로 가져온다.

                if is_tag_created:

                    tag.slug = slugify(t, allow_unicode=True)    

                    # 새로 생성된 것이 있으면 한글 처리한다.

                    tag.save()

                self.object.tags.add(tag)

            

        return response


    # dispatch

    def dispatch(self, request, *args, **kwargs):

        if request.user.is_authenticated and request.user == self.get_object().author:

            return super(PostUpdate, self).dispatch(request, *args, **kwargs)

        else:

            raise PermissionDenied

            # 권한이 없다는 것을 알려줌


class PostCreate(LoginRequiredMixin, CreateView, UserPassesTestMixin):

    model = Post # Post 모듈을 사용하겠음

    fields = ['title', 'hook_text', 'content', 'head_image', 'file_upload', 'category']

    

    def test_func(self):

        return self.request.user.is_superuser or self.request.user.is_staff

    

    def form_valid(self, form):

        current_user = self.request.user

        if current_user.is_authenticated and (current_user.is_staff or current_user.is_superuser):

            form.instance.author = current_user

            

            response = super(PostCreate, self).form_valid(form)

            tags_str = self.request.POST.get('tags_str')  # POST : post 방식으로 매서드가 온 것

            if tags_str:

                tags_str = tags_str.strip()  # strip() : 공백 제거

                tags_str = tags_str.replace(',',';')  # ,를 ;로 변경하기

                tags_list = tags_str.split(';')  # ;을 기준으로 전부 나눠짐

                

                for t in tags_list:

                    t = t.strip()

                    tag, is_tag_created = Tag.objects.get_or_create(name=t)

                    # 같은 이름을 갖는 태그가 없으면 생성하고, 있으면 그대로 가져온다.

                    if is_tag_created:

                        tag.slug = slugify(t, allow_unicode=True)    

                        # 새로 생성된 것이 있으면 한글 처리한다.

                        tag.save()

                    self.object.tags.add(tag)

            

            return response

        

        else:

            return redirect('/blog/')


class PostList(ListView):

    model = Post

    ordering = '-pk'

    # Post 나열

    # index 함수의 역할을 대신하게 된다.

    # Blog의 urls를 전부 수정해야 한다.

    

    # Older, Newer

    paginate_by = 5

    

    # None인 category가 몇 개가 있는가?

    def get_context_data(self, **kwargs):

        context = super(PostList, self).get_context_data()

        context['categories'] = Category.objects.all()

        context['no_category_post_count'] = Post.objects.filter(category=None).count()

        return context

    

class PostDetail(DetailView):

    model = Post

    

    def get_context_data(self, **kwargs):

        context = super(PostDetail,self).get_context_data()

        context['categories'] = Category.objects.all()

        context['no_category_post_count'] = Post.objects.filter(category=None).count()

        context['comment_form'] = CommentForm

        return context


# path('category/<str:slug>/',views.category_page),에서 옴

def category_page(request, slug):

    if slug == 'no_category':

        category = "미분류"    # 카테고리가 없으면 미분류

        post_list = Post.objects.filter(category=None)

    else:

        category = Category.objects.get(slug=slug)

        post_list = Post.objects.filter(category=category)

    

    return render(

        request,

        'blog/post_list.html',

        {

            'post_list':post_list,    

            'categories':Category.objects.all(), # 카드를 채워준다.

            'no_category_post_count':Post.objects.filter(category=None).count(), # 미분류, 미분류 개수 알려줌  

            'category': category, # 제목 옆에 카테고리 이름이 붙는다.

        }

    )


# 태그 페이지

def tag_page(request, slug):

    tag = Tag.objects.get(slug=slug)

    post_list = tag.post_set.all()

    

    return render(

        request,

        'blog/post_list.html',

        {

            'post_list':post_list,

            'tag':tag,

            'categories':Category.objects.all(),

            'no_category_post_count':Post.objects.filter(category=None).count(),

        }

    )


def new_comment(request, pk):

    if request.user.is_authenticated:

        post = get_object_or_404(Post, pk=pk)

        

        if request.method == 'POST':

            comment_form = CommentForm(request.POST)

            

            if comment_form.is_valid():  # 정상적으로 가져왔으면

                comment = comment_form.save(commit=False)  # 잠시 저장을 미룬다.

                comment.post = post

                comment.author = request.user

                comment.save()

                return redirect(comment.get_absolute_url())

            

        else:

            return redirect(post.get_absolute_url())

    

    else:

        raise PermissionDenied


def delete_comment(request, pk):

    comment = get_object_or_404(Comment, pk=pk)

    post = comment.post

    

    # 로그인이 되어 있고 작성자가 자신이라면

    if request.user.is_authenticated and request.user == comment.author:

        comment.delete()

        return redirect(post.get_absolute_url())

    else:

        raise PermissionDenied


class PostSearch(PostList):

    paginate_by = None  # 검색 결과를 전부 다 보여주도록 설정하기

    

    def get_queryset(self):

        q = self.kwargs['q']

        post_list = Post.objects.filter(

            Q(title__contains=q) | Q(tags__name__contains=q)

        ).distinct()  # distinct : 중복 제거

        return post_list  # 타이틀과 태그에서 찾은 자료를 중복 없는 자료를 반환

    

    def get_context_data(self, **kwargs):

        context = super(PostSearch, self).get_context_data()

        q = self.kwargs['q']

        context['search_info'] = f'Search : {q} ({self.get_queryset().count()})'

        return context

추가로 urls.py와 admin.py도 올리겠습니다. 문제점 봐주시면 감사하겠습니다.

urls.py

from django.urls import path

from . import views

# . : 현재 디렉토리(blog->urls)


# 경로 urls.py -> index.py

urlpatterns = [

    path('search/<str:q>/',views.PostSearch.as_view()),  # 글 검색하기

    path('delete_comment/<int:pk>/', views.delete_comment),

    path('update_comment/<int:pk>/', views.CommentUpdate.as_view()),

    path('update_post/<int:pk>/', views.PostUpdate.as_view()),

    path('create_post/', views.PostCreate.as_view()),

    

    path('tag/<str:slug>/',views.tag_page),

    path('<int:pk>/',views.PostDetail.as_view()),

    # path('<int:pk>/',views.single_post_page), 사용 안 함(PostDetail로 변경되었음)

    

    path('category/<str:slug>/',views.category_page),

#     views에 있는 category_page로 이동시킴

#     https://project-ztsct.run.goorm.io/blog/category/programming

#     programming만 분리해서 view.py의 category_page로 보냄 

    

    path('<int:pk>/new_comment/', views.new_comment),

    

    # path('', views.index), Class 형태로 변환되었기 때문에 주석 처리한다.

    path('',views.PostList.as_view()),

    # post_list.html 형태로 만든다.

]

- admin.py -

from django.contrib import admin

from markdownx.admin import MarkdownxModelAdmin

from .models import Post, Category, Tag, Comment


# ---------------------------------------------------------------------------


admin.site.register(Post, MarkdownxModelAdmin)

# Register your models here.


admin.site.register(Comment)


class CategoryAdmin(admin.ModelAdmin):

    prepopulated_fields = {'slug':('name', )}

    # 자동으로 slug 생성


# 태그 

class TagAdmin(admin.ModelAdmin):

    prepopulated_fields = {'slug':('name', )}

    

# post와 Category를 가지고 오기    

admin.site.register(Category, CategoryAdmin)

admin.site.register(Tag, TagAdmin)


sungyong
sungyong   1 year, 11 months ago

혹시 아래와 같은 문제가 아닌지 확인해보세요. 

https://doitdjango.com/board/qna/209/

https://doitdjango.com/board/qna/258/


Updated: Dec. 22, 2022, 10:54 p.m.

Leave a Comment:
목록보기
Search
  • 자유게시판
  • Q&A