추천을 누른 후 본래 페이지로 돌아가지 않고 오류발생

카테고리 기능을 구현하고 난 후
3-11 과정에서 추가하였던 추천을 누르고 정말로 추천하시겠습니까? 알림창의 '확인'을 누르자,

NoReverseMatch at /pybo/question/vote/316/
Reverse for 'detail' with arguments '(316,)' not found. 1 pattern(s) tried: ['pybo/question/list/(?P<category_name>[^/]+)/(?P<question_id>[0-9]+)/$']
Request Method: GET
Request URL:    http://127.0.0.1:8000/pybo/question/vote/316/
Django Version: 3.1.3
Exception Type: NoReverseMatch
Exception Value:    
Reverse for 'detail' with arguments '(316,)' not found. 1 pattern(s) tried: ['pybo/question/list/(?P<category_name>[^/]+)/(?P<question_id>[0-9]+)/$']
Exception Location: C:\Users\com\venvs\mysite\lib\site-packages\django\urls\resolvers.py, line 685, in _reverse_with_prefix
Python Executable:  C:\Users\com\venvs\mysite\Scripts\python.exe
Python Version: 3.10.6
Python Path:    
['C:\\Users\\com\\projects\\mysite',
 'C:\\Users\\com\\AppData\\Local\\Programs\\Python\\Python310\\python310.zip',
 'C:\\Users\\com\\AppData\\Local\\Programs\\Python\\Python310\\DLLs',
 'C:\\Users\\com\\AppData\\Local\\Programs\\Python\\Python310\\lib',
 'C:\\Users\\com\\AppData\\Local\\Programs\\Python\\Python310',
 'C:\\Users\\com\\venvs\\mysite',
 'C:\\Users\\com\\venvs\\mysite\\lib\\site-packages']

라는 오류 페이지가 출력됩니다. 뭐가문제인지 알 수 있을까요? 아래에는 소스코드들입니다.

base_views.py : 페이지 상세보기(detail)에서 url패턴에 임의로 카테고리를 추가하였습니다.

from django.core.paginator import Paginator
from django.shortcuts import render, get_object_or_404
from django.db.models import Q
from pybo.models import Answer, Category, Question


def index(request, category_name='qna'):
    '''
    pybo list 목록 출력
    '''
    page = request.GET.get('page', '1')  # 페이지
    kw = request.GET.get('kw','')   # 검색어

    category_list = Category.objects.all()
    category = get_object_or_404(Category, name=category_name)
    question_list = Question.objects.order_by('-create_date')
    question_list = question_list.filter(category=category)
    if kw:
        question_list = question_list.filter(
            Q(subject__icontains=kw) |  # 제목 검색
            Q(content__icontains=kw) |  # 내용 검색
            Q(answer__content__icontains=kw) |  # 답변 내용 검색
            Q(author__username__icontains=kw) |  # 질문 글쓴이 검색
            Q(answer__author__username__icontains=kw)  # 답변 글쓴이 검색
        ).distinct()
    paginator = Paginator(question_list, 10)  # 페이지당 10개씩 보여주기
    page_obj = paginator.get_page(page)
    context = {'question_list': page_obj, 'page': page, 'kw': kw, 'category_list': category_list, 'category': category }
    return render(request, 'pybo/question_list.html', context)

def detail(request,category_name,question_id):
    page = request.GET.get('page', '1')  # 페이지
    so = request.GET.get('so', 'recommend')  # 정렬기준

    question = get_object_or_404(Question, pk=question_id)
    # 요청한 question_id에 있는 답변들 필터링해서 answer_list로 명명
    answer_list = Answer.objects.filter(question=question)

    # 페이징처리
    paginator = Paginator(answer_list, 5)  # 페이지당 5개식 보여주기
    page_obj = paginator.get_page(page)

    context = {'question': question, 'answer_list': page_obj, 'page': page, 'so': so, 'category': question.category}
    return render(request, 'pybo/question_detail.html', context)


common/pybo/urls.py

from django.urls import path

from .views import base_views, question_views, answer_views, vote_views

from django.contrib.auth import views as auth_views

app_name = 'pybo'

urlpatterns = [
    # base
    path('question/list', base_views.index, name='index'),
    path('question/detail/<str:category_name>/<int:question_id>/', base_views.detail, name='detail'),
    path('question/list/<str:category_name>/', base_views.index, name='index'),

    # question
    path('question/create/<str:category_name>', question_views.question_create, name='question_create'),
    path('question/modify/<int:question_id>/', question_views.question_modify,
         name='question_modify'),
    #path('question/modify/<str:category_name>/<int:question_id>/', question_views.question_modify,name='question_modify'),
    path('question/delete/<int:question_id>/', question_views.question_delete, name='question_delete'),

    # answer
    path('answer/create/<int:question_id>/', answer_views.answer_create, name='answer_create'),
    path('answer/modify/<int:answer_id>/', answer_views.answer_modify, name='answer_modify'),
    path('answer/delete/<int:answer_id>/', answer_views.answer_delete, name='answer_delete'),

    # recommend
    path('question/vote/<int:question_id>/', vote_views.vote_question, name='vote_question'),
    path('answer/vote/<int:answer_id>/', vote_views.vote_answer, name='vote_answer'),

]

questin_detail.html

{% extends 'base.html' %}
{% block content %}
{% load pybo_filter %}
<div class="container my-3">
    <!-- message 표시 -->
    {% if messages %}
    <div class="alert alert-danger my-3" role="alert">
        {% for message in messages %}
        <strong>{{ message.tags }}</strong>
        <ul>
            <li>{{ message.message }}</li>
        </ul>
        {% endfor %}
    </div>
    {% endif %}
    <!-- 질문 -->
    <h2 class="border-bottom py-2">[{{category.description}}]{{ question.subject }}</h2>
    <div class="card my-3">
        <div class="card-body">
<!--            <div class="card-text" style="white-space: pre-line;">{{ question.content }}</div>-->
                <div class="card-text">{{ question.content|mark }}</div>
            <div class="d-flex justify-content-end">
                {% if question.modify_date %}
                <div class="badge bg-light text-dark p-2 text-start mx-3">
                    <div class="mb-2">modified at</div>
                    <div>{{ question.modify_date }}</div>
                </div>
                {% endif %}
                <div class="badge bg-light text-dark p-2 text-start">
                    <div class="mb-2">{{ question.author.username }}</div>
                    <div>{{ question.create_date }}</div>
                </div>
            </div>
            <div class="my-3">
                <a href="javascript:void(0)" data-uri="{% url 'pybo:vote_question' question.id %}"
                   class="recommend btn btn-sm btn-outline-secondary"> 추천
                    <span class="badge rounded-pill bg-success">{{question.voter.count}}</span>
                </a>
                {% if request.user == question.author %}
                <a href="{% url 'pybo:question_modify' question.id   %}"
                   class="btn btn-sm btn-outline-secondary">수정</a>
                <a href="javascript:void(0)" class="delete btn btn-sm btn-outline-secondary"
                   data-uri="{% url 'pybo:question_delete' question.id  %}">삭제</a>
                {% endif %}
            </div>
        </div>
    </div>
    <!-- 답변 -->
    <h5 class="border-bottom my-3 py-2">{{question.answer_set.count}}개의 답변이 있습니다.</h5>
    {% for answer in answer_list %}
    <div class="card my-3">
        <div class="card-body">
<!-- 답변내용 -->
<!--            <div class="card-text" style="white-space: pre-line;">{{ answer.content }}</div>-->
            <div class="card-text" >{{ answer.content|mark }}</div>
            <div class="d-flex justify-content-end">
                {% if answer.modify_date %}
                <div class="badge bg-light text-dark p-2 text-start mx-3">
                    <div class="mb-2">modified at</div>
                    <div>{{ answer.modify_date }}</div>
                </div>
                {% endif %}
                <div class="badge bg-light text-dark p-2 text-start">
                    <div class="mb-2">{{ answer.author.username }}</div>
                    <div>{{ answer.create_date }}</div>
                </div>
            </div>
            <div class="my-3">
                <a href="javascript:void(0)" data-uri="{% url 'pybo:vote_answer' answer.id  %}"
                   class="recommend btn btn-sm btn-outline-secondary"> 추천
                    <span class="badge rounded-pill bg-success">{{answer.voter.count}}</span>
                </a>
                {% if request.user == answer.author %}
                <a href="{% url 'pybo:answer_modify' answer.id  %}"
                   class="btn btn-sm btn-outline-secondary">수정</a>
                <a href="javascript:void(0)" class="delete btn btn-sm btn-outline-secondary "
                   data-uri="{% url 'pybo:answer_delete' answer.id  %}">삭제</a>
                {% endif %}
            </div>
        </div>
    </div>
    {% endfor %}
    <!-- 답변 페이징처리 시작 -->
    <ul class="pagination justify-content-center">
        <!--처음페이지-->
        <li class="page-item">
            <a class="page-link" href="?page=1">처음</a>

        <!-- 이전페이지 -->
        {% if answer_list.has_previous %}
        <li class="page-item">
            <a class="page-link" href="?page={{ answer_list.previous_page_number }}">이전</a>
        </li>
        {% else %}
        <li class="page-item disabled">
            <a class="page-link" tabindex="-1" aria-disabled="true"
               href="javascript:void(0)">이전</a>
        </li>
        {% endif %}
        <!-- 페이지리스트 -->
        {% for page_number in answer_list.paginator.page_range %}
        {% if page_number >= answer_list.number|add:-2 and page_number <= answer_list.number|add:2%}
        {% if page_number == answer_list.number %}
        <li class="page-item active" aria-current="page">
            <a class="page-link" href="?page={{ page_number }}">{{ page_number }}</a>
        </li>
        {% else %}
        <li class="page-item">
            <a class="page-link" href="?page={{ page_number }}">{{ page_number }}</a>
        </li>
        {% endif %}
        {% endif %}
        {% endfor %}
        <!-- 다음페이지 -->
        {% if answer_list.has_next %}
        <li class="page-item">
            <a class="page-link" href="?page={{ answer_list.paginator.num_pages }}">다음</a>
        </li>
        {% else %}
        <li class="page-item disabled">
            <a class="page-link" tabindex="-1" aria-disabled="true"
               href="javascript:void(0)">다음</a>
        </li>
        {% endif %}
        <!--마지막페이지-->
        <li class="page-item">
            <a class="page-link" href="?page={{ answer_list.paginator.count }}">끝</a>
        </li>
    </ul>
    <!-- 답변 페이징처리 끝 -->

    <form action="{% url 'pybo:answer_create' question.id %}" method="post" class="my-3">
        {% csrf_token %}
        {% include "form_errors.html" %}
        <div class="mb-3">
            <label for="content" class="form-label">답변내용</label>
            <textarea {% if not user.is_authenticated %}disabled{% endif %}
                      name="content" id="content" class="form-control" rows="10"></textarea>
        </div>
        <input type="submit" value="답변등록" class="btn btn-primary">
    </form>
</div>
{% endblock %}
{% block script %}
<script type='text/javascript'>
const delete_elements = document.getElementsByClassName("delete");
Array.from(delete_elements).forEach(function(element) {
    element.addEventListener('click', function() {
        if(confirm("정말로 삭제하시겠습니까?")) {
            location.href = this.dataset.uri;
        };
    });
});
const recommend_elements = document.getElementsByClassName("recommend");
Array.from(recommend_elements).forEach(function(element) {
    element.addEventListener('click', function() {
        if(confirm("정말로 추천하시겠습니까?")) {
            location.href = this.dataset.uri;
        };
    });
});
</script>
{% endblock %}

flavonoid37 283

M 2023년 5월 29일 3:43 오전

추천의 문제가 아니라 카테고리를 추가한 부분이 문제가 있어 보입니다. 카테고리 추가한 부분을 원래로 원복해도 추천이 안되는지 확인해 보세요. - 박응용님, 2023년 5월 29일 11:07 오전 추천 , 대댓글
@박응용님 url에서 detail 부분에 추가했던 <str:category.name>를 없애고, 뷰에서 받는 category_name인자들을 없애주니 이상이 없어졌습니다. - flavonoid37님, 2023년 5월 29일 10:51 오후 추천 , 대댓글
목록으로