Курсовые - РАЗРАБОТКА ОНЛАЙН-ТРЕНАЖЕРА ПО БЕЛОРУССКОМУ ЯЗЫКУ

ПРИЛОЖЕНИЕ А

(обязательное)

Листинг кода программы

from django.shortcuts import render,get_object_or_404,redirect
from django.contrib.auth.decorators import login_required
from .forms import FindWordForm, TakeQuizForm
import pdb
from .dictionary import Parcer
from .models import Regulation
from django.db import transaction
from django.db.models import Count, Max
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView
from django.views.generic.base import TemplateView
from .models import Quiz, Student, TakenQuiz
from django.contrib import messages
from datetime import timedelta, datetime

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


class BoardTemplateView(LoginRequiredMixin, TemplateView):
    login_url = '/account/login/'
    template_name = 'dashboard.html'


class RuleListView(LoginRequiredMixin, ListView):
    login_url = '/account/login/'
    template_name = 'list_rules.html'
    model = Regulation
    context_object_name = 'rules'


class SelectedRuleListView(LoginRequiredMixin, ListView):
    login_url = '/account/login/'
    template_name = 'full_rules.html'
    model = Regulation

    def get_context_data(self, *args, **kwargs) :
        context = super() .get_context_data(*args, **kwargs)
        context['current_rule'] = get_object_or_404(Regulation, pk=self.kwargs['rules_id'])
        return context


@login_required (login_url = '/account/login/')
def dictionary(request):
    search_word = ''
    if request.method == 'POST':
        form= FindWordForm(request.POST)        
        if form.is_valid():
            search_word= form.cleaned_data['word']
            parcer = Parcer()
            search_word = parcer.getExplanationOfWord(parcer.getPageWitfoundedWord(search_word))

    else:
        form= FindWordForm()
    context= {'form': form, 'word': search_word}
    return render(request, 'dictionary.html', context)


class QuizListView(LoginRequiredMixin, ListView):
    model = Quiz
    ordering = ('name', )
    context_object_name = 'quizzes'
    template_name = 'quiz_list.html'

    def get_queryset(self):
        student = self.request.user.student   #“Аннотирует” каждый объект в QuerySet агрегированным значением (среднее, суииа и др.), которое будет вычислено из данных связанных объектов, которые связанны с объектами из``QuerySet``.
        taken_quizzes = student.quizzes.values_list('pk', flat=True) #достаем квизы, которые еще не выполнены и кол-во вопросов больше 0
        queryset = Quiz.objects.exclude(pk__in=taken_quizzes) \
                               .annotate(questions_count=Count('questions')) \
                               .filter(questions_count__gt=0)#достаем квизы, которые были выполнены не ранее 2 часов
        old_tests = student.taken_quizzes.values('quiz').annotate(max=Max('date')) \
                               .filter(max__lt=datetime.now() - timedelta(hours=2)) \
                               .values_list('quiz', flat=True)
        print(old_tests)
        old_tests_queryset = Quiz.objects.filter(pk__in=old_tests) \
                                         .annotate(questions_count=Count('questions')).distinct()#??
        queryset = queryset.union(old_tests_queryset)
        return queryset

# в список квизов добавить, те которые старше 3 дней, перед выполнением проверить был ли этот кветс пройден ранее,
# если так, тогда удалить все ответы студента, в пройденных тестах показывать еще и дату.
class TakenQuizListView(LoginRequiredMixin, ListView):
    model = TakenQuiz
    context_object_name = 'taken_quizzes'
    template_name = 'taken_quiz_list.html'

    def get_queryset(self): #Возвращает QuerySet который автоматически включает в выборку данные связанных объектов при выполнении запроса.
        queryset = self.request.user.student.taken_quizzes.select_related('quiz').order_by('quiz__name')
        return queryset


@login_required
def take_quiz(request, pk):
    quiz = get_object_or_404(Quiz, pk=pk)
    student = request.user.student

    if student.quizzes.filter(pk=pk).exists(): #проверяем квизы, которые послучайности запушены, но время блокировки еще не вышло
        if student.taken_quizzes.filter(pk=pk,date__gt=datetime.now() - timedelta(hours=2)) \
                                .values_list('quiz', flat=True) \
                                .exists():
            return render(request, 'taken_quiz_list.html')

    total_questions = quiz.questions.count()
    unanswered_questions = student.get_unanswered_questions(quiz)
    total_unanswered_questions = unanswered_questions.count()
    progress = 100 - round(((total_unanswered_questions - 1) / total_questions) * 100)

    if request.method == 'POST':
        question = []
        if request.POST.get('answer') is None:
            question = unanswered_questions.first()
        else:
            for i in unanswered_questions.filter(answers__pk=request.POST['answer']):
                question = i
                  
        form = TakeQuizForm(question=question, data=request.POST)
        if form.is_valid():
            with transaction.atomic():
                student_answer = form.save(commit=False)
                student_answer.student = student
                student_answer.save()
                if student.get_unanswered_questions(quiz).exists():
                    return redirect('take_quiz', pk)
                else:
                    correct_answers = student.quiz_answers.filter(answer__question__quiz=quiz,
                                                                  taken_quiz=None,
                                                                  answer__is_correct=True).count()
                    score = round((correct_answers / total_questions) * 100.0, 2)
                    new_taken_quiz = TakenQuiz.objects.create(student=student, quiz=quiz, score=score)
                    student.quiz_answers.filter(answer__question__quiz=quiz, taken_quiz=None) \
                                               .update(taken_quiz=new_taken_quiz.pk)
                    if score < 50.0:
                        messages.warning(request, 'У наступным разе будзе лепей %s лік %s.'
                                         % (quiz.name, score))
                    else:
                        messages.success(request, 'Мае віншаванні, %s! Твой лік %s.' % (quiz.name, score))
                    return redirect('quiz_list')
    else:
        unanswered_questions = unanswered_questions.order_by('?')    
        question = unanswered_questions.first()
        form = TakeQuizForm(question=question)

    return render(request, 'take_quiz_form.html', {
        'quiz': quiz,
        'question': question,
        'form': form,
        'progress': progress
    })

models.py

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

class Regulation(models.Model):
    title = models.CharField(max_length=50,verbose_name='Назва правіла')
    content = models.TextField(null=True, blank=True,verbose_name='Тэкст')

    def __str__(self):
        return self.title

    class Meta:
        verbose_name_plural='Правілы'
        verbose_name='Правіла'


class Quiz(models.Model):
    rule = models.ForeignKey(Regulation, on_delete=models.PROTECT,verbose_name='Правіла')
    explanation = models.TextField(blank=True, verbose_name='Агульнае заданне')
    name = models.CharField(max_length=255)
    
    def __str__(self):
        return self.explanation

    class Meta:
        verbose_name='Заданне для практыкавання'

class Task(models.Model):
    quiz = models.ForeignKey(Quiz, on_delete=models.PROTECT, verbose_name='Пытанне да задання',
                             related_name='questions')
    question = models.TextField(verbose_name='Тэкст заданія', blank=True)


    def __str__(self):
        return self.question
        
    class Meta:
        verbose_name_plural='Заданні'
        verbose_name='Заданне'


class Answer(models.Model):
    question = models.ForeignKey(Task, on_delete=models.CASCADE, related_name='answers')
    text = models.CharField('Адказ', max_length=255)
    is_correct = models.BooleanField('Правільны адказ', default=False)

    def __str__(self):
        return self.text

 


class Student(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    quizzes = models.ManyToManyField(Quiz, through='TakenQuiz')
    # through Kласс модели, которая представляет связующую таблицу (связующая модель)
    # либо в виде ссьmки на него, либо в виде имени, представленном стро­кой.

    def get_unanswered_questions(self, quiz):
        answered_questions = self.quiz_answers \
            .filter(answer__question__quiz=quiz, taken_quiz=None) \
            .values_list('answer__question__pk', flat=True) # получаем объекты через таблицу studentAnswer по ключу answer,
                                                            # далее из таббл Answer по ключу question получаем сам запрос
                                                            # массив из ключей отвеченных вопросов
        questions = quiz.questions.exclude(pk__in=answered_questions).order_by('question')
        return questions

    

    def __str__(self):
        return self.user.username


class TakenQuiz(models.Model):
    student = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='taken_quizzes')
    quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE, related_name='taken_quizzes')
    score = models.FloatField()
    date = models.DateTimeField(auto_now_add=True)


class StudentAnswer(models.Model):
    student = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='quiz_answers')
    answer = models.ForeignKey(Answer, on_delete=models.CASCADE, related_name='+')
    taken_quiz = models.ForeignKey(TakenQuiz, on_delete=models.CASCADE,
                                   related_name='taken_quiz_answers',
                                   null=True)

forms.py

from django import forms

from .models import (Answer, StudentAnswer)


class FindWordForm(forms.Form):
    word = forms.CharField(max_length=100)
     

class TakeQuizForm(forms.ModelForm):
    answer = forms.ModelChoiceField(
        queryset=Answer.objects.none(),
        widget=forms.RadioSelect(),
        required=True,
        empty_label=None,
        label="Тваі адказы")

    class Meta:
        model = StudentAnswer
        fields = ('answer', )

    def __init__(self, *args, **kwargs):
        question = kwargs.pop('question')
        super().__init__(*args, **kwargs)
        self.fields['answer'].queryset = question.answers.order_by('?')

dictionary.py

import requests
from bs4 import BeautifulSoup

class Parcer():
    
    def getPageWitfoundedWord(self, word):
        payload = {'term': word, 'lang': 'beld'}
        r = requests.get('https://www.skarnik.by/search', params = payload)
        soup = BeautifulSoup(r.text, "lxml")
        return soup

    def getExplanationOfWord(self, soup):
        data=[]
        try:
            data = list(filter(None, soup.find(id="trn").text.split('\xa0')))
            data[0] = soup.title.text
        except:
            tags = soup.div.find_all(class_="span10")
            for tag in tags:
                try:
                    data.append(tag.find('p').text)
                    break
                except:
                    continue
        return data


urls.py

from django.urls import path
from . import views

urlpatterns = [
 path('', views.index, name='index'),
 path('dashboard/', views.BoardTemplateView.as_view(), name='dashboard'),
 path('dashboard/dictionary/', views.dictionary, name='dictionary'),
 path('dashboard/rules/', views.RuleListView.as_view(), name='list_of_rules'),
 path('dashboard/rules/<int:rules_id>', views.SelectedRuleListView.as_view(), name='full_rules'),
 path('dashboard/quiz/', views.QuizListView.as_view(), name='quiz_list'),
 path('dashboard/taken/', views.TakenQuizListView.as_view(), name='taken_quiz_list'),
 path('dashboard/quiz/<int:pk>/', views.take_quiz, name='take_quiz'),
]

 

Количество комментариев: 0

Для того, чтобы оставить коментарий необходимо зарегистрироваться
Дата Выполнено, %
2020-05-19 19:37:36 10
2020-05-14 09:03:38 100
Открытая Для скрытия необходимо уменьшить величину статуса выполнения.