Search code examples
django-viewsdjango-templatesdjango-urlsdjango-url-reverse

trouble converting Python regex to path with django


I am working on a project which uses regex urls. The way it is currently designed is you have to manually type the url as a model field which then gets passed to the urls/views as an argument? (I don't fully understand this part yes, still learning). These are the views, urls, and the templates which I think are the issue here. I am trying to automatize the process of adding the slug and that part is working. However, I can't seem to find a way around getting it to work with the way urls are configured currently.

the views sections:

class QuizDetailView(DetailView):
    model = Quiz
    slug_field = 'url'
    template_name = 'exam/quiz_detail.html'

another section of the view where I think the url from the above snippet is turned into a variable which then gets used in url:

class QuizTake(FormView):
    form_class = QuestionForm
    template_name = 'exam/question.html'

def dispatch(self, request, *args, **kwargs):
    self.quiz = get_object_or_404(Quiz, url=self.kwargs['quiz_name'])
    if self.quiz.draft and not request.user.has_perm('quiz.change_quiz'):
        raise PermissionDenied

The urls:

#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=QuizTake.as_view(),
        name='quiz_question'),

and finally the template snippets, this is a detail view of the model/quiz:

<a href="{% url 'quiz_start_page' quiz.url %}">

this one displays the model (which is a quiz users take):

<a href="{% url 'quiz_question' quiz_name=quiz.url %}">

What I have tried so far:

first, since I have the slug field:

class QuizDetailView(DetailView):
    model = Quiz
    slug_field = 'url' ---this was commented out
    template_name = 'exam/quiz_detail.html'

next, I changed the urls from:

url(regex=r'^(?P<slug>[\w-]+)/$',
        view=QuizDetailView.as_view(),
        name='quiz_start_page'),
url(regex=r'^(?P<quiz_name>[\w-]+)/take/$',
        view=QuizTake.as_view(),
        name='quiz_question'),

to:

path('<slug:slug>/', QuizDetailView.as_view(), name='quiz_start_page'),
path('<slug:slug>', QuizTake.as_view(), name='quiz_question'),

Then I changed the temlates from:

<a href="{% url 'quiz_start_page' quiz.url %}">
<a href="{% url 'quiz_question' quiz_name=quiz.url %}">

To:

<a href="{% url 'quiz_start_page' quiz.slug %}">
<a href="{% url 'quiz_question' quiz.slug %}">

When I click on the listview for the model/quiz, the url is displayed correctly on browser which I think means the automatic slug is working. However, once I click the link I see this error:

Reverse for 'quiz_question' with keyword arguments '{'quiz_name': ''}' not found. 1 pattern(s) tried: ['(?P<slug>[-a-zA-Z0-9_]+)$']

Really appreciate any help/pointers


Solution

  • Just figured it out myself, I realized I left out the argument which links the Quiz to the TakeQuiz model above.

    path('<quiz_name>', QuizTake.as_view(), name='quiz_question'),
    

    Above, instead of the slug I passed the argument <quiz_name> and changed the templates too:

    {% url 'quiz_question' quiz_name=quiz.slug %}
    

    That worked.