from django.shortcuts import render from django.http import HttpResponse, JsonResponse from django.views import generic from django.template import loader from django.urls import reverse_lazy from .models import ArrowCount from .forms import ArrowCountForm from django.contrib.auth.decorators import login_required from django.conf import settings from django.core.exceptions import SuspiciousOperation from django.utils.translation import gettext as _ from django.db.models.functions import Extract, ExtractWeek from django.db.models import Sum from datetime import datetime, timedelta, date import json from django.core.serializers.json import DjangoJSONEncoder # https://stackoverflow.com/questions/5882405 def tofirstdayinisoweek(year, week): ret = datetime.strptime('%04d-%02d-1' % (year, week), '%Y-%W-%w') if date(year, 1, 4).isoweekday() > 4: ret -= timedelta(days=7) return ret def index(request): template = loader.get_template('index.html') return HttpResponse(template.render({}, request)) def count_stats(request): template = loader.get_template('stats.html') # Group counts by week (extract isoyear works only on psql and DB2) weeklyArrows = ArrowCount.objects \ .filter(user = request.user) \ .annotate(isoyear=Extract('date', lookup_name='isoyear')) \ .annotate(week=ExtractWeek('date')) \ .values('isoyear', 'week') \ .annotate(sum_count=Sum('count')) \ .order_by('-isoyear', '-week') for w in weeklyArrows: w['weekStarts'] = tofirstdayinisoweek(w['isoyear'], w['week']) w['weekEnds'] = w['weekStarts'] + timedelta(days=6) return HttpResponse(template.render({ 'weeklyArrows': json.dumps(list(weeklyArrows), cls=DjangoJSONEncoder) }, request)) @login_required def arrow_count_list(request): page = request.GET.get('page') if not page: page = 1 else: page = int(page) if page <= 0: raise SuspiciousOperation(_("page is negative or 0")) start = settings.ITEMS_PER_PAGE * (page - 1) finish = settings.ITEMS_PER_PAGE + start counts = ArrowCount.objects.order_by('-date') \ .filter(user = request.user)[start:finish] pageCount = ArrowCount.objects.filter(user = request.user).count() / \ settings.ITEMS_PER_PAGE template = loader.get_template('counter/list.html') return HttpResponse(template.render({ 'counts': counts, 'pageCount': pageCount, 'page': page }, request)) class NewArrowCount(generic.CreateView): form_class = ArrowCountForm success_url = reverse_lazy('count_list') template_name = 'counter/new.html' def form_valid(self, form): form.instance.user = self.request.user return super().form_valid(form) class EditArrowCount(generic.UpdateView): form_class = ArrowCountForm success_url = reverse_lazy('count_list') template_name = 'counter/edit.html' def get_object(self, queryset=None): obj = ArrowCount.objects.get(id=self.kwargs['id']) return obj def get(self, request, *args, **kwargs): super().get(self, request, *args, **kwargs) context_data = self.get_context_data() context_data.update(ac_id=self.kwargs['id']) return self.render_to_response(context_data) class DeleteArrowCount(generic.DeleteView): model = ArrowCount success_url = reverse_lazy('count_list') def get_object(self, queryset=None): obj = ArrowCount.objects.get(id=self.kwargs['id']) return obj @login_required def arrow_count_update_ajax(request, ac_id): try: count = int(request.POST.get("count", None)) except ValueError: return JsonResponse({ 'success': False, 'error': _('count is not a number') }) if count == None or count < 0: return JsonResponse({ 'success': False, 'error': _('count is negative or 0') }) arrow_count = ArrowCount.objects.filter( id=ac_id, user=request.user)[0] if arrow_count == None: return JsonResponse({ 'success': False, 'error': _('ArrowCount instance not found or from different user') }) arrow_count.count = count arrow_count.save() return JsonResponse({ 'success': True, 'count': arrow_count.count })