indici/src/gradebook/views.py
2022-06-30 15:12:40 -06:00

298 lines
8.7 KiB
Python

from django.shortcuts import render
from django.urls import reverse_lazy, reverse
from django.views.generic.base import TemplateView
from django.views.generic.edit import FormView, CreateView, UpdateView, DeleteView
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.forms.models import inlineformset_factory
from django import forms
from django.db.models import ( Exists, OuterRef,
Prefetch, Subquery, Count, Sum, Avg, F, Q, Value)
from django.db.models.functions import Length, Upper
from students.models import Student, Thread, Message
from .models import (
Tag,
Subject,
Component,
Score,
)
from .forms import ComponentForm, ComponentUpdateForm
# UPLOAD CSV
# import pandas as pd
# csv_data = pd.read_csv('file.csv', sep=';')
# products = [
# Product(
# name = csv_data.ix[row]['Name'],
# description = csv_data.ix[row]['Description'],
# price = csv_data.ix[row]['price'],
# )
# for row in csv_data['ID']
# ]
# Product.objects.bulk_create(products)
# if form.is_valid():
# csv_file = form.cleaned_data['csv_file']
class SearchResultsView(ListView):
model = Component
template_name = 'gradebook/search_results.html'
def get_queryset(self):
query = self.request.GET.get('q')
object_list = Component.objects.filter(
Q(name__icontains=query) | Q(tags__name__icontains=query)
).prefetch_related(
Prefetch(
'score_set',
queryset=Score.objects.select_related('student')
),
'tags'
).annotate(
grade_avg_pre=Avg('score__value')
).order_by('subject')
return object_list
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
query = self.request.GET.get('q')
context['student_list'] = Student.objects.filter(
Q(first_name__icontains=query) | Q(last_name__icontains=query) | Q(student_id__icontains=query)
)
context['message_list'] = Message.objects.filter(
Q(content__icontains=query)
)
context['query'] = query
return context
# SUBJECTS
class SubjectListView(LoginRequiredMixin, ListView):
model = Subject
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['tag_list'] = Tag.objects.annotate(Count('component'))
return context
class SubjectCreateView(LoginRequiredMixin, CreateView):
model = Subject
template_name_suffix = '_create_form'
fields = ('__all__')
class SubjectDetailView(LoginRequiredMixin, DetailView):
model = Subject
def get_object(self):
queryset = Subject.objects.filter(
pk=self.kwargs.get(self.pk_url_kwarg)
).prefetch_related(
Prefetch('component_set', queryset=Component.objects.prefetch_related(
'score_set'
).annotate(
grade_avg_pre=Avg('score__value')
))
)
obj = queryset.get()
return obj
class SubjectUpdateView(LoginRequiredMixin, UpdateView):
model = Subject
fields = ('__all__')
def get_success_url(self):
pk = self.kwargs["pk"]
return reverse('subject-detail', kwargs={'pk': pk})
class SubjectDeleteView(LoginRequiredMixin, DeleteView):
model = Subject
success_url = reverse_lazy('subject-list')
# COMPONENTS
class ComponentListView(LoginRequiredMixin, ListView):
model = Component
pk_url_kwarg = 'comp_pk'
class ComponentCreateView(LoginRequiredMixin, CreateView):
model = Component
form_class = ComponentForm
template_name_suffix = '_create_form'
pk_url_kwarg = 'comp_pk'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['subject'] = Subject.objects.get(pk=self.kwargs['pk'])
return context
def form_valid(self, form):
form.instance.subject = Subject.objects.get(pk=self.kwargs['pk'])
return super().form_valid(form)
def get_success_url(self):
return reverse('component-detail', kwargs={'pk': self.kwargs['pk'], 'comp_pk': self.object.pk})
class ComponentDetailView(LoginRequiredMixin, DetailView):
model = Component
pk_url_kwarg = 'comp_pk'
def get_object(self):
queryset = Component.objects.filter(
pk=self.kwargs.get(self.pk_url_kwarg)
).prefetch_related(
Prefetch(
'score_set',
queryset=Score.objects.select_related('student')
),
'tags'
).annotate(
grade_avg_pre=Avg('score__value')
)
obj = queryset.get()
return obj
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
cscores = Score.objects.filter(
component=self.object,
student=OuterRef('pk')
)
context['scoreless'] = Student.objects.exclude(
score__in=cscores
)
return context
class ComponentUpdateView(LoginRequiredMixin, UpdateView):
model = Component
form_class = ComponentUpdateForm
pk_url_kwarg = 'comp_pk'
def get_success_url(self):
return reverse('subject-detail', kwargs={'pk': self.object.subject.pk})
class ComponentManagerView(LoginRequiredMixin, UpdateView):
model = Component
fields = ('finished_grading',)
pk_url_kwarg = 'comp_pk'
template_name_suffix = '_manager'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
cscores = Score.objects.filter(
component=self.object,
student=OuterRef('pk')
)
context['student_list'] = Student.objects.annotate(
cscore=Subquery(cscores.values('value')),
cscore_pk=Subquery(cscores.values('pk'))
)
return context
def get_success_url(self):
return reverse('component-detail', kwargs={'pk': self.object.subject.pk, 'comp_pk': self.object.pk})
def form_valid(self, form):
form.save()
for key, value in self.request.POST.items():
if 'student' in key and value:
s_pk = key.split('_')[1]
obj, created = Score.objects.update_or_create(
component=self.object,
student=Student.objects.get(pk=s_pk),
defaults={'value': value}
)
return super().form_valid(form)
class ComponentDeleteView(LoginRequiredMixin, DeleteView):
model = Component
pk_url_kwarg = 'comp_pk'
def get_success_url(self):
return reverse('subject-detail', kwargs={'pk': self.kwargs['pk']})
# SCORES
class ScoreListView(LoginRequiredMixin, ListView):
model = Score
class ScoreCreateView(LoginRequiredMixin, CreateView):
model = Score
template_name_suffix = '_create_form'
fields = ('__all__')
def get_success_url(self):
return reverse('component-detail', kwargs={'pk': self.object.component.pk})
class ScoreDetailView(LoginRequiredMixin, DetailView):
model = Score
class ScoreUpdateView(LoginRequiredMixin, UpdateView):
model = Score
fields = ['value']
def get_success_url(self):
return reverse('component-detail', kwargs={'pk': self.object.component.subject.pk, 'comp_pk': self.object.component.pk})
class ScoreDeleteView(LoginRequiredMixin, DeleteView):
model = Score
def get_success_url(self):
return reverse('component-detail', kwargs={'pk': self.object.component.subject.pk, 'comp_pk': self.object.component.pk})
# TAGS
class TagListView(LoginRequiredMixin, ListView):
model = Tag
def get_queryset(self):
object_list = Tag.objects.annotate(Count('component'))
return object_list
class TagCreateView(LoginRequiredMixin, CreateView):
model = Tag
template_name_suffix = '_create_form'
fields = ('__all__')
class TagDetailView(LoginRequiredMixin, DetailView):
model = Tag
def get_object(self):
queryset = Tag.objects.filter(
pk=self.kwargs.get(self.pk_url_kwarg)
).prefetch_related(
Prefetch('component_set', queryset=Component.objects.prefetch_related(
'score_set'
).annotate(
grade_avg_pre=Avg('score__value')
))
)
obj = queryset.get()
return obj
class TagUpdateView(LoginRequiredMixin, UpdateView):
model = Tag
fields = ('__all__')
def get_success_url(self):
pk = self.kwargs["pk"]
return reverse('tag-detail', kwargs={'pk': pk})
class TagDeleteView(LoginRequiredMixin, DeleteView):
model = Tag
success_url = reverse_lazy('tag-list')