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')