没有反向匹配错误

时间:2014-08-06 14:06:04

标签: django django-urls

我试图通过引用这个来制作quiz_application。https://github.com/tomwalker/django_quiz

当我尝试访问类别页面时,我收到此错误。

NoReverseMatch at /quiz/category/
Reverse for 'quiz_category_list_matching' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: ['quiz/category/(?P<category_name>[\\w-]+)/$']

我的文件正在关注, urls.py

from django.conf.urls import patterns, url

from .views import QuizListView, CategoriesListView,\
    ViewQuizListByCategory, QuizUserProgressView, QuizDetailView


urlpatterns = patterns('quiz.views',

                       url(regex=r'^$',
                           view=QuizListView.as_view(),
                           name='quiz_index'),

                       url(regex=r'^category/$',
                           view=CategoriesListView.as_view(),
                           name='quiz_category_list_all'),

                       url(regex=r'^category/(?P<category_name>[\w.-]+)/$',
                           view=ViewQuizListByCategory.as_view(),
                           name='quiz_category_list_matching'),


                       url(regex=r'^progress/$',
                           view=QuizUserProgressView.as_view(),
                           name='quiz_progress'),

                       #  passes variable 'quiz_name' to quiz_take view
                       url(regex=r'^(?P<slug>[\w-]+)/$',
                           view=QuizDetailView.as_view(),
                           name='quiz_start_page'),

                       url(regex=r'^(?P<quiz_name>[\w-]+)/take/$',
                           view='quiz_take',
                           name='quiz_question'),
                       )

views.py

import random

from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, render, render_to_response
from django.template import RequestContext
from django.utils.decorators import method_decorator
from django.views.generic import DetailView, ListView, TemplateView

from .models import Quiz, Category, Progress, Sitting, Question


class QuizListView(ListView):
    model = Quiz


class QuizDetailView(DetailView):
    model = Quiz
    slug_field = 'url'


class CategoriesListView(ListView):
    model = Category


class ViewQuizListByCategory(ListView):
    model = Quiz
    template_name = 'view_quiz_category.html'

    def get_context_data(self, **kwargs):
        context = super(ViewQuizListByCategory, self)\
            .get_context_data(**kwargs)

        category = get_object_or_404(Category,
                                     category=self.kwargs['category_name'])
        context['category'] = category
        return context

    def get_queryset(self):
        category = get_object_or_404(Category,
                                     category=self.kwargs['category_name'])
        queryset = super(ViewQuizListByCategory, self).get_queryset()
        return queryset.filter(category=category)


class QuizUserProgressView(TemplateView):
    template_name = 'progress.html'

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(QuizUserProgressView, self)\
            .dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(QuizUserProgressView, self).get_context_data(**kwargs)

        progress = get_object_or_404(Progress, user=self.request.user)
        context['cat_scores'] = progress.list_all_cat_scores()
        context['exams'] = progress.show_exams()

        return context


def quiz_take(request, quiz_name):
    quiz = Quiz.objects.get(url=quiz_name.lower())

    if request.user.is_authenticated() is True:
        return user_load_sitting(request, quiz)

    else:  # anon user
        return anon_load_sitting(request, quiz)


def user_load_sitting(request, quiz):
    if quiz.single_attempt is True and\
       Sitting.objects.filter(user=request.user,
                              quiz=quiz,
                              complete=True)\
                      .count() > 0:

        return render(request, 'single_complete.html')

    try:
        sitting = Sitting.objects.get(user=request.user,
                                      quiz=quiz,
                                      complete=False)

    except Sitting.DoesNotExist:
        sitting = Sitting.objects.new_sitting(request.user, quiz)

    except Sitting.MultipleObjectsReturned:
        sitting = Sitting.objects.filter(user=request.user,
                                         quiz=quiz,
                                         complete=False)[0]

    finally:
        return user_load_next_question(request, sitting, quiz)


def user_load_next_question(request, sitting, quiz):
    previous = False
    if 'guess' in request.GET:
        progress, created = Progress.objects.get_or_create(user=request.user)
        guess = request.GET['guess']
        question = sitting.get_first_question()
        is_correct = question.check_if_correct(guess)

        if is_correct is True:
            sitting.add_to_score(1)
            progress.update_score(question.category, 1, 1)

        else:
            sitting.add_incorrect_question(question)
            progress.update_score(question.category, 0, 1)

        if quiz.answers_at_end is not True:
            previous = {'previous_answer': guess,
                        'previous_outcome': is_correct,
                        'previous_question': question,
                        'answers': question.get_answers(),
                        'question_type': {question.__class__.__name__: True}}

        sitting.remove_first_question()

    next_q = sitting.get_first_question()
    if next_q is False:
        #  no questions left
        return final_result_user(request, sitting, quiz, previous)

    return render_to_response('question.html',
                              {'quiz': quiz,
                               'question': next_q,
                               'question_type': {next_q.__class__.__name__:
                                                 True},
                               'answers': next_q.get_answers(),
                               'previous': previous},
                              context_instance=RequestContext(request))


def final_result_user(request, sitting, quiz, previous):
    score = sitting.get_current_score
    incorrect = sitting.get_incorrect_questions()
    max_score = quiz.get_max_score
    incorrect_score = max_score - score
    percent = sitting.get_percent_correct

    sitting.mark_quiz_complete()

    if quiz.exam_paper is False:  # if we do not plan to store the outcome
        sitting.delete()

    if quiz.answers_at_end is False:
        return render_to_response('result.html',
                                  {'quiz': quiz,
                                   'score': score,
                                   'max_score': max_score,
                                   'incorrect_score':incorrect_score,
                                   'percent': percent,
                                   'previous': previous},
                                  context_instance=RequestContext(request))
    else:
        questions = quiz.get_questions()
        return render_to_response('result.html',
                                  {'quiz': quiz,
                                   'score': score,
                                   'max_score': max_score,
                                   'incorrect_score':incorrect_score,
                                   'percent': percent,
                                   'questions': questions,
                                   'incorrect_questions': incorrect},
                                  context_instance=RequestContext(request))


def anon_load_sitting(request, quiz):
    if quiz.single_attempt is True:
        return render(request, 'single_complete.html')

    if quiz.anon_q_list() in request.session:
        return load_anon_next_question(request, quiz)
    else:
        return new_anon_quiz_session(request, quiz)


def new_anon_quiz_session(request, quiz):
    """
    Sets the session variables when starting a quiz for the first time
    """
    request.session.set_expiry(259200)  # expires after 3 days
    questions = quiz.get_questions()
    question_list = [question.id for question in questions]
    if quiz.random_order is True:
        random.shuffle(question_list)

    # session score for anon users
    request.session[quiz.anon_score_id()] = 0

    # session list of questions
    request.session[quiz.anon_q_list()] = question_list

    return load_anon_next_question(request, quiz)


def load_anon_next_question(request, quiz):
    previous = False

    if 'guess' in request.GET:
        previous = question_check_anon(request, quiz)
        request.session[quiz.anon_q_list()] = (request.
                                               session[quiz.anon_q_list()][1:])

    if not request.session[quiz.anon_q_list()]:
        return final_result_anon(request, quiz, previous)

    next_question_id = request.session[quiz.anon_q_list()][0]
    next_question = Question.objects.get_subclass(id=next_question_id)
    question_type = {next_question.__class__.__name__: True}
    return render_to_response('question.html',
                              {'quiz': quiz,
                               'question': next_question,
                               'question_type': question_type,
                               'previous': previous},
                              context_instance=RequestContext(request))


def question_check_anon(request, quiz):
    question = Question.objects.get_subclass(id=request.GET['question_id'])
    is_correct = question.check_if_correct(request.GET['guess'])

    if is_correct is True:
        request.session[quiz.anon_score_id()] += 1
        anon_session_score(request, 1, 1)
    else:
        anon_session_score(request, 0, 1)

    if quiz.answers_at_end is not True:
        return {'previous_answer': request.GET['guess'],
                'previous_outcome': is_correct,
                'previous_question': question}
    else:
        return {}


def anon_session_score(request, to_add=0, possible=0):
    """
    Returns the session score for non-signed in users.
    If number passed in then add this to the running total and
    return session score

    examples:
        anon_session_score(1, 1) will add 1 out of a possible 1
        anon_session_score(0, 2) will add 0 out of a possible 2
        x, y = anon_session_score() will return the session score
                                    without modification
    """
    if "session_score" not in request.session:
        request.session["session_score"] = 0
        request.session["session_score_possible"] = 0

    if possible > 0:
        request.session["session_score"] = (request.session["session_score"] +
                                            to_add)

        request.session["session_score_possible"] = \
            (request.session["session_score_possible"] + possible)

    return request.session["session_score"], \
        request.session["session_score_possible"]


def final_result_anon(request, quiz, previous):
    score = request.session[quiz.anon_score_id()]
    max_score = quiz.get_max_score
    incorrect_score = max_score - score
    percent = int(round((float(score) / max_score) * 100))
    if score is 0:
        score = "0"

    session_score, session_possible = anon_session_score(request)
    del request.session[quiz.anon_q_list()]

    if quiz.answers_at_end is False:
        return render_to_response('result.html',
                                  {'score': score,
                                   'max_score': max_score,
                                   'incorrect_score':incorrect_score,
                                   'percent': percent,
                                   'previous': previous,
                                   'session': session_score,
                                   'possible': session_possible},
                                  context_instance=RequestContext(request))
    else:
        questions = quiz.get_questions()
        return render_to_response('result.html',
                                  {'score': score,
                                   'max_score': max_score,
                                   'incorrect_score':incorrect_score,
                                   'percent': percent,
                                   'questions': questions,
                                   'session': session_score,
                                   'possible': session_possible},
                                  context_instance=RequestContext(request))

category_list.html

{% extends 'base.html' %}
{% block title %}All Quizzes{% endblock %}

{% block content %}
<h2>Category list</h2>

<ul>
  {% for cat in category_list %}
  <li>
    <a href="{% url 'quiz_category_list_matching' category_name=cat.category %}">
      {{ cat.category }}
    </a>
  </li>
  {% endfor %}
</ul>

{% endblock %}

我认为问题是url.py,因为我在搜索时得到了一些信息。 哪部分错了?

  • 我理解问题是我无法将category_list.html中的category_name传递给urls.py,因为当我删除<a href="{% url 'quiz_category_list_matching' category_name=cat.category %}">时,即使未链接类别列表也能正常工作。 你能给我一些解决这个问题的想法。

1 个答案:

答案 0 :(得分:0)

默认情况下,CBV中的Django会将模型分配给object_list,以覆盖分配名称,更改context_object_name属性:

class CategoriesListView(ListView):
    model = Category
    context_object_name = "category_list"