commit
3e4ca8155e
18 changed files with 482 additions and 3 deletions
@ -0,0 +1,16 @@ |
||||
from django.http import HttpResponseForbidden |
||||
|
||||
|
||||
class CheckPerm(object): |
||||
@staticmethod |
||||
def process_request(request): |
||||
if '/admin' in request.path or "/management" in request.path \ |
||||
or '/analytics' in request.path: |
||||
|
||||
if not request.user.is_authenticated(): |
||||
return HttpResponseForbidden() |
||||
|
||||
if not (request.user.in_role == "M" or request.user.in_role == "S" |
||||
or request.user.in_role == "A" or request.user.is_admin): |
||||
|
||||
return HttpResponseForbidden() |
||||
@ -0,0 +1,10 @@ |
||||
from django.conf.urls import url |
||||
from analytics import views |
||||
|
||||
urlpatterns = [ |
||||
url(r'^$', views.index_view), |
||||
url(r'^theme/$', views.index_view_access_theme), |
||||
url(r'^theme/new/$', views.new_view_access_theme), |
||||
url(r'^homework/$', views.index_view_homework_wait), |
||||
url(r'^homework/new/$', views.new_view_homework_wait), |
||||
] |
||||
@ -0,0 +1,155 @@ |
||||
from django.shortcuts import render_to_response, redirect, render |
||||
import time, os, csv |
||||
from datetime import date |
||||
|
||||
from lms.settings import MEDIA_ROOT |
||||
|
||||
from courses.models import Course, CourseTheme, Homework, Exam |
||||
from journals.models import CourseThemeJ, HomeworkTry, ExamTry |
||||
|
||||
index_view = lambda request: render_to_response('analytics/index.html') |
||||
|
||||
|
||||
def index_view_decor(url): |
||||
def wrap(func): |
||||
def get_request(request): |
||||
start = request.GET.get('start', '') |
||||
end = request.GET.get('end', '') |
||||
|
||||
path = MEDIA_ROOT + url + 's' + start + 'e' + end + 'progress.csv' |
||||
|
||||
try: |
||||
with open(path, newline='') as file: |
||||
reader = csv.reader(file, delimiter=',', quotechar='|') |
||||
max = 0 |
||||
res = [] |
||||
for row in reader: |
||||
max = max if max > len(row) else len(row) |
||||
res1 = [] |
||||
for i in row: |
||||
k = i.split("$-$") |
||||
k = {'value': k[0], 'background': 'none'}\ |
||||
if len(i.split("$-$")) == 1 else {'value': k[0],'background': k[1]} |
||||
res1.append(k) |
||||
|
||||
res.append(res1) |
||||
for i in res: |
||||
for j in range(max - len(i)): |
||||
i.append({'value': 0, 'background': 'none'}) |
||||
first = ['Курсы'] |
||||
for i in range(max - 1): |
||||
first.append("Тема " + str(i + 1)) |
||||
except FileNotFoundError: |
||||
return redirect(url + "new/?start=" + start + "&end=" + end) |
||||
|
||||
date_create = time.ctime(os.stat(path).st_atime) |
||||
|
||||
context = { |
||||
'body': res, |
||||
'header': first, |
||||
'date_create': date_create, |
||||
'start': start, |
||||
'end': end, |
||||
'url': url, |
||||
} |
||||
|
||||
context.update(func()) |
||||
|
||||
return render(request, url[1:-1] + '.html', context=context) |
||||
|
||||
return get_request |
||||
|
||||
return wrap |
||||
|
||||
|
||||
@index_view_decor("/analytics/theme/") |
||||
def index_view_access_theme(): |
||||
return {} |
||||
|
||||
|
||||
@index_view_decor("/analytics/homework/") |
||||
def index_view_homework_wait(): |
||||
return {} |
||||
|
||||
|
||||
def new_view_decor(url): |
||||
def wrap(func): |
||||
def get_request(request): |
||||
start = request.GET.get('start', '') |
||||
end = request.GET.get('end', '') |
||||
|
||||
path = MEDIA_ROOT + url + 's' + start + 'e' + end + 'progress.csv' |
||||
|
||||
start_date = None |
||||
end_date = None |
||||
|
||||
try: |
||||
start_date = date(*[int(i) for i in start.split('-')]) |
||||
end_date = date(*[int(i) for i in end.split('-')]) |
||||
except ValueError: |
||||
pass |
||||
|
||||
if not check_date_validate(start_date, end_date): |
||||
return redirect(url) |
||||
|
||||
try: |
||||
with open(path, 'w', newline='') as csvfile: |
||||
func(end_date, start_date, csvfile) |
||||
return redirect(url + "?start=" + start + "&end=" + end) |
||||
|
||||
except FileNotFoundError: |
||||
os.makedirs(MEDIA_ROOT + url) |
||||
return redirect(url + "new/?start=" + start + "&end=" + end) |
||||
|
||||
return get_request |
||||
|
||||
return wrap |
||||
|
||||
|
||||
@new_view_decor("/analytics/theme/") |
||||
def new_view_access_theme(end_date, start_date, csvfile): |
||||
for course in Course.objects.order_by('sort'): |
||||
list = [course.title] |
||||
for i in CourseTheme.objects.filter(course=course): |
||||
kwargs = { |
||||
'material': i, |
||||
'success': True, |
||||
} |
||||
if end_date: |
||||
kwargs['student__last_time__lte'] = end_date |
||||
if start_date: |
||||
kwargs['student__last_time__gte'] = start_date |
||||
list.append(str(len(CourseThemeJ.objects.filter(**kwargs))) + ( |
||||
"$-$yellow" if i._type == 'Ex' else "")) |
||||
writercsv = csv.writer(csvfile, delimiter=',', quotechar='|') |
||||
writercsv.writerow(list) |
||||
|
||||
|
||||
@new_view_decor("/analytics/homework/") |
||||
def new_view_homework_wait(end_date, start_date, csvfile): |
||||
for course in Course.objects.order_by('sort'): |
||||
list = [course.title] |
||||
for i in CourseTheme.objects.filter(course=course): |
||||
kwargs = { |
||||
'success': False, |
||||
'expired': False, |
||||
'f_date': None |
||||
} |
||||
if end_date: |
||||
kwargs['student__last_time__lte'] = end_date |
||||
if start_date: |
||||
kwargs['student__last_time__gte'] = start_date |
||||
list.append(str( |
||||
len(HomeworkTry.objects.filter(material=Homework.objects.filter(theme=i), **kwargs)) + |
||||
len(ExamTry.objects.filter(material=Exam.objects.filter(theme=i), **kwargs)) |
||||
)) |
||||
writercsv = csv.writer(csvfile, delimiter=',', quotechar='|') |
||||
writercsv.writerow(list) |
||||
|
||||
|
||||
def check_date_validate(start=None, end=None): |
||||
if start: |
||||
if end: |
||||
return (start < end) and (end < date.today()) |
||||
return start < date.today() |
||||
return end < date.today() if end else True |
||||
|
unable to load file from base commit
|
|
unable to load file from base commit
|
|
unable to load file from base commit
|
|
unable to load file from base commit
|
|
unable to load file from base commit
|
|
unable to load file from base commit
|
@ -0,0 +1,41 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<title>Аналитика</title> |
||||
</head> |
||||
<body> |
||||
<h2>Дата создания отчёта {{ date_create }}</h2> |
||||
<button><a href="new?start={{ start }}&end={{ end }}">Сгенирировать отчёт</a></button> |
||||
<button style="margin-bottom: 20px"><a href="/media{{ url }}s{{ start }}e{{ end }}progress.csv">Скачать отчёт</a></button> |
||||
<button><a href="/analytics">На главную</a></button> |
||||
<form action=""> |
||||
<label>от</label> |
||||
<input name="start" type="date" value="{{ start }}"> |
||||
<label>до</label> |
||||
<input name="end" type="date" value="{{ end }}"> |
||||
<button type="submit">Подготовить отчёт</button> |
||||
</form> |
||||
|
||||
<table border="1px"> |
||||
<tr> |
||||
{% for i in header %} |
||||
<th>{{ i }}</th> |
||||
{% endfor %} |
||||
</tr> |
||||
{% for i in body %} |
||||
<tr> |
||||
{% for j in i %} |
||||
<td style="background: {{j.background}}">{{ j.value }}</td> |
||||
{% endfor %} |
||||
</tr> |
||||
{% endfor %} |
||||
</table> |
||||
<p> |
||||
{% block description %}{% endblock %} |
||||
</p> |
||||
|
||||
<h2>Внимание! Новый отчёт генерируется 1 раз! Следите за записью в хедоре страницы, если вы нуждаетесь в обновлении <br> |
||||
данных жмите кнопку "Сгенерировать отчёт" таким образом вы получите обновлённые данные для заданных пораметров фильтрации</h2> |
||||
</body> |
||||
</html> |
||||
@ -0,0 +1,2 @@ |
||||
{% extends 'analytics/base.html' %} |
||||
{% block description %}{% endblock %} |
||||
@ -0,0 +1,12 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<title>Аналитика</title> |
||||
</head> |
||||
<body> |
||||
<h2>Меню поиска</h2> |
||||
<h4><a href="theme">Студентов успешно прошедших тему</a></h4> |
||||
<h4><a href="homework">Студентов ожидающих проверки домашки</a></h4> |
||||
</body> |
||||
</html> |
||||
@ -0,0 +1,9 @@ |
||||
{% extends 'analytics/base.html' %} |
||||
{% block description %} |
||||
В данной таблице представлены данные о том, сколько студентов прошло заданную тему. <br> |
||||
Темы не всегда проходятся последовательно, поэтому порой тему с большим порядковым номером прошло большее количество пользовавтелей. <br> |
||||
Вы можите выставить фильтр по последней акутивности пользователя, фильтр может быть ограничивающим с одной стороны или может отсутствовать, <br> |
||||
в случае ввода невалидных данных ошибки не происходит вас просто перенапровляет на начальную страницу. <br> |
||||
Вы можите скачать отчёт в формате csv метка $-$yellow говорит о том что в данной теме есть экзамен,<br> |
||||
в таблице темы содержашие экзамен подсвечены жёлтым светом |
||||
{% endblock %} |
||||
Loading…
Reference in new issue