Как я могу отображать данные из модели django и сохранять их одновременно, используя представления на основе классов?

Я создаю приложение для викторины, используя Django. Требования следующие:

  1. Мне нужно сначала отобразить все темы, доступные для викторины, на главной странице.
  2. При нажатии на определенную страницу нас должно перенаправлять на новую страницу, где мы увидим вопросы.
  3. Каждый раз должен отображаться один вопрос.
  4. Кнопка next должна загружать следующий вопрос, и пользователь не может вернуться к предыдущему вопросу.
  5. После прохождения всех вопросов, пользователь должен быть переведен на другую страницу, на которой отображается результат.
  6. Для каждого вопроса, который пытаются решить, процесс должен отображаться как 5/10 вопрос, 6/10 вопрос.
  7. Если пользователь выходит из системы до завершения теста, ему должен быть показан тот же вопрос, когда он войдет в систему.

У меня получается отображать темы .

Проблема в том, что я не могу отобразить один вопрос за раз и сохранить ответ пользователя, используя представление на основе класса. Также я запутался, как мне отобразить прогресс и сохранить запись пользователя, если он/она выходит из системы, не завершив тест, и перенаправить его на следующий вопрос, до которого он пытался ответить.

Я новичок в django и пытаюсь разработать это. Пожалуйста, помогите!

Делюсь своим кодом:

Models.py

from django.db import models
from django.contrib.auth.models import User
import uuid

class Topic(models.Model):
    t_id = models.UUIDField(
         primary_key = True,
         default = uuid.uuid4,
         editable = False)
    topic = models.CharField(max_length=200)
    time_required = models.IntegerField(help_text="Duration of Quizz in minutes")

    def __str__(self):
        return f"{self.topic}"


class Question(models.Model):
    q_id = models.UUIDField(
         primary_key = True,
         default = uuid.uuid4,
         editable = False)
    question = models.CharField(max_length=200)
    topic = models.ForeignKey(Topic, on_delete=models.CASCADE)

    def __str__(self):
        return self.question

class Answer(models.Model):
    a_id = models.UUIDField(
         primary_key = True,
         default = uuid.uuid4,
         editable = False)
    answer= models.CharField(max_length=100)
    is_correct=models.BooleanField(default=False)
    question=models.ForeignKey(Question, on_delete=models.CASCADE)
    

    def __str__(self):
        return f"{self.answer}"


class UserRecord(models.Model):
    User=models.ForeignKey(User, on_delete=models.CASCADE)
    question=models.CharField(max_length=100)
    answer_choosen=models.CharField(max_length=100)

    def __str__(self):
        return f"{self.User} | {self.question} | {self.answer_choosen}"

views.py

from django.views.generic import ListView
from django.contrib.auth.decorators import login_required
from .models import Topic, Question, Answer, UserRecord
from django.utils.decorators import method_decorator
from django.shortcuts import render,redirect


@method_decorator(login_required, name='dispatch')
class TopicView(ListView):
    model = Topic
    template_name = 'quiz/topic.html'
    context_object_name = 'topics'

    

def nextques(request,t_id):
    
    questions=Question.objects.filter(topic=t_id)
    total_questions=[]
    for question in questions:
        total_questions.append(str(question.q_id))
    user_answered=UserRecord.objects.filter(User=request.user)
    answered_list=[]
    for answered_question in user_answered:
        answered_list.append(str(answered_question.question))
    for question_id in total_questions:
        if question_id not in answered_list:
            questionset=Question.objects.filter(q_id=question_id)
            answerset=Answer.objects.filter(question=question_id)
            break
        else:
            continue
    context={
        "questions":questionset,
        "answers":answerset,
    }
    if request.method=="POST":
        user=request.user
        question_id=request.POST.get('hidden1')     
        question=request.POST.get('hidden')
        answer_id=request.POST.get(question)
        query=UserRecord(User=user,question=question_id,answer_choosen=answer_id)
        query.save()
    if len(user_answered)<len(total_questions):
        return render(request, "quiz/quizz.html", context=context)
    else:
        return render(request, "quiz/quizend.html")

base.html

topic.html

{% extends "quiz/base.html" %}
{% load static %}

{% block title %}
Quiz
{% endblock %}

{% block scripts %}
    <script src="{% static 'quiz/topic.js' %}" defer></script>
{% endblock scripts %}

{% block content %}

<div class="modal fade" id="quizModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <h5 class="modal-title" id="staticBackdropLabel">Start Quiz ?</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body" id="modalbody">
        </div>
        <div class="modal-footer">
            <button type="button" class="btn btn-danger" data-bs-dismiss="modal">No</button>
            <button id="start-button" type="button" class="btn btn-success">Yes, Start</button>
        </div>
    </div>
</div>
</div>

    <div class="container mr-4">
        <div class="h1">Topics</div>
        <hr />

        {% for obj in topics %}
            <button class="btn btn-secondary modal-button" 
            data-bs-pk="{{obj.t_id}}"
            data-bs-topic="{{obj.topic}}" 
             data-bs-time="{{obj.time_required}}"
             data-bs-toggle="modal"
             data-bs-target="#quizModal">
                {{obj.topic}}
            </button><br /><br />
        {% endfor %}
    </div>
{% endblock %}

topic.js

const modalBtns = [...document.getElementsByClassName('modal-button')]
const modalBody = document.getElementById('modalbody')
const startBtn = document.getElementById('start-button')

const url = window.location.href

modalBtns.forEach(modalBtn=> modalBtn.addEventListener('click', ()=>{
    const id = modalBtn.getAttribute('data-bs-pk')
    const topic = modalBtn.getAttribute('data-bs-topic')
    const time = modalBtn.getAttribute('data-bs-time')

    modalBody.innerHTML = `
        <div class="h5 mb-3">Are you sure you want to begin "<b>${topic}</b>"?</div>
        <div class="text-muted">
                Time: <b>${time} mins</b>
        </div>
    `
    startBtn.addEventListener('click', ()=>{
        window.location.href = url + id
    })
}))

quizend.html

{% extends "quiz/base.html" %}

{% block content %}
    <h1>This is QuizEnd</h1>
{% endblock content %}

quiz.html

{% extends "quiz/base.html" %}
{% load static %}

{% block title %}

{% endblock title %}

{% block scripts %}
    <script>
        const url=window.location.href
    </script>
{% endblock scripts %}
{% block content %}
    <div class="container">
        <form id="quiz-form" action="" method="POST" class="mt-3 mb-3">
            {% csrf_token %}
            <div id="quiz-box">
                {% for question in questions %}
                        {{question}}<br />
                        {% for answer in answers %}
                            <div class="form-check">
                                <input type="hidden" name="hidden1" value="{{question.q_id}}">
                                <input type="hidden" name="hidden" value="{{question}}">
                                <input type="radio" class="ans" id="{{question}}-{{answer}}" name="{{question}}" value="{{answer.a_id}}" required>
                                <label for="{{question}}">{{answer}}</label>
                            </div>
                        {% endfor %}<br />
                    {% endfor %}
                <br />
            </div> 
            <button type="submit" class="btn btn-primary mt-3">Next</button>
        </form>
    </div>
{% endblock content %}

quiz/urls.py

from django.urls import path
from .import views
from .views import TopicView #QuestionListView,


urlpatterns = [
    path('', TopicView.as_view(), name='topic'),
    path('<t_id>', views.nextques, name='quiz'),
]

urls.py

"""quiz_proj URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from users import views as user_views
from django.contrib.auth import views as auth_views
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('quiz.urls')),
    path('register/', user_views.register, name= 'register'),
    path('login/', auth_views.LoginView.as_view(template_name='users/login.html'), name = 'login'),
    path('logout/', auth_views.LogoutView.as_view(template_name='users/logout.html'), name = 'logout'),
]

Попробуйте с DetailView. Django Docs

Вернуться на верх