Unable to create a dynamic routing in Django

Hi there

I am working on a project where I have pretty much set up the website using HTML, CSS and Django as a backend. I am trying to navigate from one link to another using dynamic routing in Django. I can dynamically move between different sections of the first layer but when I try to navigate to the second layer it won’t work. Let me give details below for better understanding of my issue.

Navigatation bar [ Home Aboutus Quiz Login ]

If quiz button is pressed the first layer of navigation buttons appear as follows:

                          [Number         Algebra          Geometry   etc.... ]

I can retrieve all sub topics under the above topics on the left pane of the page and leave the right pane until one of the options below is selected.

e.g. Number 1
     Number 2
     Number 3
     etc..

My issue now is when Number 1 is pressed, for example, I want to display its contents on the right pane.

This is how I am trying to achieve it:

========================================================================

view.py

from django.shortcuts import render
from django.http import HttpResponse

from .models import Sub_Topic, Topic, Quiz

# Create your views here.
def index(request):
    return render(request, 'quiz_app/index.html')

def aboutus(request):
    #return HttpResponse("About us under construction")
    return render(request, 'quiz_app/aboutus.html')

def quiz_sub_topics(request,pk):
    sub_topics = Sub_Topic.objects.filter(topic_id=pk)
    context = {
        'sub_top':sub_topics,
    }
    return render(request, 'quiz_app/quiz.html', context)

def quiz_sub_topic_questions(request,slug):
    sub_topic_questions = Quiz.objects.filter(sub_topic_name=str(slug))
    
    context = {
        'sub_top_que':sub_topic_questions,
    }
    return render(request, 'quiz_app/quiz.html', context)

def login(request):
    return render(request, 'login.html')

=================================================
urls.py (under my_app)

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name = 'index'),
    path('aboutus/', views.aboutus, name='aboutus'),
    path('quiz/<int:pk>/', views.quiz_sub_topics, name='quiz_sub_topics'),
    path('quiz/<int:pk>/<slug:slug>/',views.quiz_sub_topic_questions, name='quiz_sub_topic_questions'),    
]

=========================================================

models.py

from django.db import models
import json

# Create your models here.

class Topic(models.Model):
    topic_id = models.BigAutoField(primary_key=True)
    topic_name = models.CharField(max_length=100)
    
    def __str__(self):
        return str(self.topic_name)
    
class Sub_Topic(models.Model):
    sub_topic_id = models.BigAutoField(primary_key=True)
    sub_topic_name = models.CharField(max_length=100)
    topic = models.ForeignKey(Topic , on_delete = models.CASCADE)
    
    def __str__(self):
        return str(self.sub_topic_name)
    
class Quiz(models.Model):
    quiz_id = models.BigAutoField(primary_key=True)
    question = models.CharField(max_length=200)
    options = models.CharField(max_length=200)
    answer = models.CharField(max_length = 20)
    sub_topic_name = models.ForeignKey(Sub_Topic, on_delete = models.CASCADE)   
    
    def __str__(self):
        return str(self.question)
    
    
class Student(models.Model):
    student_id = models.BigAutoField(primary_key=True)
    email  = models.CharField(max_length=100)
    password = models.CharField(max_length=100)
    quiz = models.ManyToManyField(Quiz)
    
    
class Result(models.Model):
    result_id = models.BigAutoField(primary_key=True)
    percentage = models.DecimalField(max_digits=10, decimal_places=2)
    result_date = models.DateTimeField(max_length=50)
    student = models.ForeignKey(Student, on_delete = models.CASCADE)
 

=============================================================

admin.py

from django.contrib import admin
from .models import Quiz, Topic, Sub_Topic, Student, Result

# Register your models here.
admin.site.register(Quiz)
admin.site.register(Topic)
admin.site.register(Sub_Topic)
admin.site.register(Result)
admin.site.register(Student)

===================

I have tried everything to no avail. Please I need your help. What I am doing wrong?

Thanks.

Welcome @pth2020 !

Side note: When posting code, templates, error messages, or other preformatted text here, enclose the code between lines of three backtick - ` characters. This means you’ll have a line of ```, then your code, then another line of ```. This forces the forum software to keep your code properly formatted. (I’ve taken the liberty of fixing your original post for you.)

What specifically isn’t working for you here? (What are you seeing that you’re not expecting to see? Or what are you not seeing that you expect to see?)

Also, what does your quiz_app/quiz.html template look like?

Thank you very much Ken for welcoming me to the forum and trying to help me with solving the problem. Thanks also for formatting my code. -

So When the url (through a link in the navigation) is entered it displays the first layer of subtopics list:

Number - http: // 127 . 0 . 0 . 1 : 8888/ quiz / 1 /
etc,

What I am now trying to do is under each section (Number, Algebra etc) I have subtopics
Under Number ( e.g. number1, number2, number3, …)
Under Algebra (e.g. algebra1, algebra2, algebra3…)

I want to link number1 with its content using this url
http: // 127 . 0 . 0 . 1 : 8888/ quiz / 1 / number1/
However, I am not getting the desired output from the link above.
The output I am getting it as follows:

|Request Method:|GET|
| --- | --- |
|Request URL:|****/quiz/1/Fractions/|
|Django Version:|5.0.4|
|Exception Type:|TypeError|
|Exception Value:|quiz_sub_topic_questions() got an unexpected keyword argument 'pk'|

My quiz . html

<div class="card">                    
                    <a h r e f ="http :  //   127   .  0.  0  .  1 :  8888  /  quiz  /  1  /  "  >Number</  a>
                </div>

......

{% for st in sub_top %}
                        
                            <div class="card">
                                <a href="./{{st.sub_topic_id}}/">{{st.sub_topic_name}}</a>
                            </div>           
                        

                    {% endfor %}


.....

{% for stq in sub_top_que  %}                    
                        <div class="card"> 
                            <div class="quest">{{stq.question}}</div>

                        </div>
                        {% endfor %}

Thank you very much @KenWhitesell for welcoming me to the forum and trying helping me with solving the problem. Thanks also for formatting my code. -

So When the url (through a link in the navigation) is entered it displays the first layer of subtopics list:

Number - http://127.0.0.1:8000/1/
etc,

What I am now trying to do is under each section (Number, Algebra etc) I have subtopics
Under Number ( e.g. number1, number2, number3, …)
Under Algebra (e.g. algebra1, algebra2, algebra3…)

I want to link number1 with its list using url http://127.0.0.1:8000/1/number1/ and get all questions
related to number1 subtopic.
However, I am not getting the desired output from the link above.
The output I am getting it as follows:

{% extends "base.html" %}
{% block content %}
    <!-- Area of study cards -->
    <section class="area-of-study">
        <div class="area-of-study-container">
            <div class="area-of-study-grid">
                <div class="card">                    
                    <a href="http://127.0.0.1:8888/quiz/1/">Number</a>
                </div>
                <div class="card">
                    another link...
                </div>
                <div class="card">
                    another link...
                </div>
                <div class="card">
                    another link...
                </div>
                <div class="card">
                   another link...
                </div>    
            </div>
        </div>
    </section>
    <!-- Topics -->
    <section>
        <div class="topic-questions">
            <div class="topic-container">
                <div class="topic-grid">

                    {% for st in sub_top %}
                        
                            <div class="card">
                                <a href="./{{st.sub_topic_id}}/">{{st.sub_topic_name}}</a>
                            </div>           
                        

                    {% endfor %}

                </div>
            </div>

            <div class="questions-container">
                <div class="questions-grid">
                    <form action="#">
                        <p>test</p>
                        {% for stq in sub_top_que  %}                    
                        <div class="card"> 
                            <div class="quest">{{stq.question}}</div>

                        </div>
                        {% endfor %}
                        
                        <div class="btn">
                            <button class="button">Submit Quiz</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </section>
    {% endblock content %}

Side note: When marking off blocks of code, you need to use the backtick - `, not the apostrophe - '. (Fixed in these current posts.) Also, add replies to this topic, do not open up new topics on this thread.)

Your url for this is:

Which means it’s going to pass two parameters to the view - pk and slug. However, the view is defined to only take one parameter:

Thanks for your reply. Apologies for creating new threads. I can be excused for being a newbie :laughing:

So if the view is defined to take only one parameter how do I get around accessing
(http://127.0.0.1:8888/1/number1/ )
without specifying the path below?

path('quiz/<int:pk>/<slug:slug>/', view.quiz_sub_topic_questions, name.quiz_sub_topic_questions')

Change your view definition to accept both parameters.

As in

`
def quiz_sub_topic_questions(request, pk, slug):

sub_topic_questions = Quiz.objects.filter(topic_id= pk, sub_topic_name=str(slug))    
context = {
    'sub_top_que':sub_topic_questions,
}

return render(request, 'quiz_app/quiz.html', context)

`

Yes, that’s the basic idea.

However, there’s nothing that requires you to use that parameter within the view. You’re only required to define the view itself to accept that parameter.

Thank you very much! I have been struggling with this for the last 4/5 days.

It is now working. Learned so much from you from just one thread.
I do follow your replies in some other forums and cannot appreciate you enough for your dedicated support to those of us learning Django.

Hi Ken

Hope all is well with you.

I just changed the configuration a little bit and got into trouble again.
Just want to bother you one more time.

Instead of numbers in the url I wanted to use meanigful words.

views.py

def quiz(request): return render(request,'quiz_app/quiz-menu.html')

def quiz_sub_topics(request,my_slug): sub_topics = None sub_topics = Sub_Topic.objects.filter(topic=my_slug) context = { 'sub_top':sub_topics, } return render(request, 'quiz_app/quiz.html', context)

def quiz_sub_topic_questions(request, slug, slug1): sub_topic_questions = Quiz.objects.filter(sub_topic=slug1) context = { 'sub_top_que':sub_topic_questions, } return render(request, 'quiz_app/quiz.html', context)

urls.py

urlpatterns = [ path('', views.index, name = 'index'), path('aboutus/', views.aboutus, name='aboutus'), path('quiz/',views.quiz, name='quiz'), path('/quiz/<slug:my_slug/', views.quiz_sub_topics, name='quiz_sub_topics'), path('/quiz/<slug:slug>/<slug:slug1>/',views.quiz_sub_topic_questions, name='quiz_sub_topic_questions'), ]

And the error I am getting…

Using the URLconf defined ingcse_project.urls`, Django tried these URL patterns, in this order:

  1. admin/
  2. [name=‘index’]
  3. aboutus/ [name=‘aboutus’]
  4. quiz/ [name=‘quiz’]
  5. /quiz/<slug:my_slug/ [name=‘quiz_sub_topics’]
  6. /quiz/slug:slug/slug:slug1/ [name=‘quiz_sub_topic_questions’]

The current path, quiz/number/, didn’t match any of these.
`