init
This commit is contained in:
BIN
analytics/__pycache__/admin.cpython-313.pyc
Normal file
BIN
analytics/__pycache__/admin.cpython-313.pyc
Normal file
Binary file not shown.
BIN
analytics/__pycache__/models.cpython-313.pyc
Normal file
BIN
analytics/__pycache__/models.cpython-313.pyc
Normal file
Binary file not shown.
BIN
analytics/__pycache__/urls.cpython-313.pyc
Normal file
BIN
analytics/__pycache__/urls.cpython-313.pyc
Normal file
Binary file not shown.
BIN
analytics/__pycache__/views.cpython-313.pyc
Normal file
BIN
analytics/__pycache__/views.cpython-313.pyc
Normal file
Binary file not shown.
20
analytics/admin.py
Normal file
20
analytics/admin.py
Normal file
@ -0,0 +1,20 @@
|
||||
from django.contrib import admin
|
||||
from .models import CourseAnalytics, InstructorAnalytics, StudentAnalytics
|
||||
|
||||
@admin.register(CourseAnalytics)
|
||||
class CourseAnalyticsAdmin(admin.ModelAdmin):
|
||||
list_display = ('course', 'total_students', 'average_progress', 'completion_rate', 'revenue', 'created_at', 'updated_at')
|
||||
list_filter = ('created_at', 'updated_at')
|
||||
search_fields = ('course__title',)
|
||||
|
||||
@admin.register(InstructorAnalytics)
|
||||
class InstructorAnalyticsAdmin(admin.ModelAdmin):
|
||||
list_display = ('instructor', 'total_lessons', 'total_students', 'average_rating', 'completion_rate', 'created_at', 'updated_at')
|
||||
list_filter = ('created_at', 'updated_at')
|
||||
search_fields = ('instructor__profile__user__username', 'instructor__profile__user__email')
|
||||
|
||||
@admin.register(StudentAnalytics)
|
||||
class StudentAnalyticsAdmin(admin.ModelAdmin):
|
||||
list_display = ('student', 'total_lessons', 'attendance_rate', 'average_grade', 'created_at', 'updated_at')
|
||||
list_filter = ('created_at', 'updated_at')
|
||||
search_fields = ('student__profile__user__username', 'student__profile__user__email')
|
56
analytics/migrations/0001_initial.py
Normal file
56
analytics/migrations/0001_initial.py
Normal file
@ -0,0 +1,56 @@
|
||||
# Generated by Django 5.0.2 on 2025-06-10 20:05
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('instructor', '0001_initial'),
|
||||
('schedule', '0003_alter_lesson_options_remove_lesson_lesson_type_and_more'),
|
||||
('student', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CourseAnalytics',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('total_students', models.IntegerField(default=0)),
|
||||
('average_progress', models.DecimalField(decimal_places=2, default=0, max_digits=5)),
|
||||
('completion_rate', models.DecimalField(decimal_places=2, default=0, max_digits=5)),
|
||||
('revenue', models.DecimalField(decimal_places=2, default=0, max_digits=10)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='schedule.course')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='InstructorAnalytics',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('total_lessons', models.IntegerField(default=0)),
|
||||
('total_students', models.IntegerField(default=0)),
|
||||
('average_rating', models.DecimalField(decimal_places=2, default=5.0, max_digits=3)),
|
||||
('completion_rate', models.DecimalField(decimal_places=2, default=0, max_digits=5)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('instructor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='instructor.instructor')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='StudentAnalytics',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('total_lessons', models.IntegerField(default=0)),
|
||||
('attendance_rate', models.DecimalField(decimal_places=2, default=0, max_digits=5)),
|
||||
('average_grade', models.DecimalField(decimal_places=2, default=0, max_digits=3)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='student.student')),
|
||||
],
|
||||
),
|
||||
]
|
20
analytics/migrations/0002_alter_courseanalytics_course.py
Normal file
20
analytics/migrations/0002_alter_courseanalytics_course.py
Normal file
@ -0,0 +1,20 @@
|
||||
# Generated by Django 5.0.2 on 2025-06-10 20:24
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('analytics', '0001_initial'),
|
||||
('course', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='courseanalytics',
|
||||
name='course',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='course.course'),
|
||||
),
|
||||
]
|
0
analytics/migrations/__init__.py
Normal file
0
analytics/migrations/__init__.py
Normal file
BIN
analytics/migrations/__pycache__/0001_initial.cpython-313.pyc
Normal file
BIN
analytics/migrations/__pycache__/0001_initial.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
analytics/migrations/__pycache__/0002_initial.cpython-313.pyc
Normal file
BIN
analytics/migrations/__pycache__/0002_initial.cpython-313.pyc
Normal file
Binary file not shown.
BIN
analytics/migrations/__pycache__/0003_initial.cpython-313.pyc
Normal file
BIN
analytics/migrations/__pycache__/0003_initial.cpython-313.pyc
Normal file
Binary file not shown.
BIN
analytics/migrations/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
analytics/migrations/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
41
analytics/models.py
Normal file
41
analytics/models.py
Normal file
@ -0,0 +1,41 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from course.models import Course
|
||||
from schedule.models import Lesson
|
||||
from instructor.models import Instructor
|
||||
from student.models import Student
|
||||
|
||||
class CourseAnalytics(models.Model):
|
||||
course = models.ForeignKey(Course, on_delete=models.CASCADE)
|
||||
total_students = models.IntegerField(default=0)
|
||||
average_progress = models.DecimalField(max_digits=5, decimal_places=2, default=0)
|
||||
completion_rate = models.DecimalField(max_digits=5, decimal_places=2, default=0)
|
||||
revenue = models.DecimalField(max_digits=10, decimal_places=2, default=0)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"Аналитика курса {self.course.title}"
|
||||
|
||||
class InstructorAnalytics(models.Model):
|
||||
instructor = models.ForeignKey(Instructor, on_delete=models.CASCADE)
|
||||
total_lessons = models.IntegerField(default=0)
|
||||
total_students = models.IntegerField(default=0)
|
||||
average_rating = models.DecimalField(max_digits=3, decimal_places=2, default=5.00)
|
||||
completion_rate = models.DecimalField(max_digits=5, decimal_places=2, default=0)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"Аналитика инструктора {self.instructor}"
|
||||
|
||||
class StudentAnalytics(models.Model):
|
||||
student = models.ForeignKey(Student, on_delete=models.CASCADE)
|
||||
total_lessons = models.IntegerField(default=0)
|
||||
attendance_rate = models.DecimalField(max_digits=5, decimal_places=2, default=0)
|
||||
average_grade = models.DecimalField(max_digits=3, decimal_places=2, default=0)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"Аналитика студента {self.student}"
|
13
analytics/urls.py
Normal file
13
analytics/urls.py
Normal file
@ -0,0 +1,13 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
app_name = 'analytics'
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.analytics_dashboard, name='analytics_dashboard'),
|
||||
path('courses/', views.course_analytics, name='course_analytics'),
|
||||
path('instructors/', views.instructor_analytics, name='instructor_analytics'),
|
||||
path('students/', views.student_analytics, name='student_analytics'),
|
||||
path('reports/', views.generate_reports, name='generate_reports'),
|
||||
path('export/', views.export_data, name='export_data'),
|
||||
]
|
78
analytics/views.py
Normal file
78
analytics/views.py
Normal file
@ -0,0 +1,78 @@
|
||||
from django.shortcuts import render
|
||||
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||
from .models import CourseAnalytics, InstructorAnalytics, StudentAnalytics
|
||||
from schedule.models import Course, Lesson, LessonEnrollment
|
||||
from instructor.models import Instructor
|
||||
from student.models import Student
|
||||
import json
|
||||
from django.http import HttpResponse
|
||||
|
||||
def is_admin(user):
|
||||
return user.profile.user_type == 'admin'
|
||||
|
||||
@login_required
|
||||
@user_passes_test(is_admin)
|
||||
def analytics_dashboard(request):
|
||||
course_analytics = CourseAnalytics.objects.all()
|
||||
instructor_analytics = InstructorAnalytics.objects.all()
|
||||
student_analytics = StudentAnalytics.objects.all()
|
||||
|
||||
return render(request, 'analytics/dashboard.html', {
|
||||
'course_analytics': course_analytics,
|
||||
'instructor_analytics': instructor_analytics,
|
||||
'student_analytics': student_analytics
|
||||
})
|
||||
|
||||
@login_required
|
||||
@user_passes_test(is_admin)
|
||||
def course_analytics(request):
|
||||
courses = Course.objects.all()
|
||||
analytics = CourseAnalytics.objects.filter(course__in=courses)
|
||||
return render(request, 'analytics/course_analytics.html', {
|
||||
'courses': courses,
|
||||
'analytics': analytics
|
||||
})
|
||||
|
||||
@login_required
|
||||
@user_passes_test(is_admin)
|
||||
def instructor_analytics(request):
|
||||
instructors = Instructor.objects.all()
|
||||
analytics = InstructorAnalytics.objects.filter(instructor__in=instructors)
|
||||
return render(request, 'analytics/instructor_analytics.html', {
|
||||
'instructors': instructors,
|
||||
'analytics': analytics
|
||||
})
|
||||
|
||||
@login_required
|
||||
@user_passes_test(is_admin)
|
||||
def student_analytics(request):
|
||||
students = Student.objects.all()
|
||||
analytics = StudentAnalytics.objects.filter(student__in=students)
|
||||
return render(request, 'analytics/student_analytics.html', {
|
||||
'students': students,
|
||||
'analytics': analytics
|
||||
})
|
||||
|
||||
@login_required
|
||||
@user_passes_test(is_admin)
|
||||
def generate_reports(request):
|
||||
# Здесь будет логика генерации отчетов
|
||||
return render(request, 'analytics/reports.html')
|
||||
|
||||
@login_required
|
||||
@user_passes_test(is_admin)
|
||||
def export_data(request):
|
||||
data = {
|
||||
'courses': list(Course.objects.values()),
|
||||
'instructors': list(Instructor.objects.values()),
|
||||
'students': list(Student.objects.values()),
|
||||
'lessons': list(Lesson.objects.values()),
|
||||
'enrollments': list(LessonEnrollment.objects.values())
|
||||
}
|
||||
|
||||
response = HttpResponse(
|
||||
json.dumps(data, ensure_ascii=False),
|
||||
content_type='application/json'
|
||||
)
|
||||
response['Content-Disposition'] = 'attachment; filename="analytics_data.json"'
|
||||
return response
|
Reference in New Issue
Block a user