Merge pull request #1567 from MITx/jth/admindash
Improved /admin_dashboard
This commit is contained in:
@@ -1,39 +1,82 @@
|
||||
# Create your views here.
|
||||
import json
|
||||
from datetime import datetime
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.http import Http404
|
||||
from mitxmako.shortcuts import render_to_response
|
||||
|
||||
from student.models import CourseEnrollment, CourseEnrollmentAllowed
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
def dictfetchall(cursor):
|
||||
'''Returns all rows from a cursor as a dict.
|
||||
'''Returns a list of all rows from a cursor as a column: result dict.
|
||||
Borrowed from Django documentation'''
|
||||
desc = cursor.description
|
||||
return [
|
||||
dict(zip([col[0] for col in desc], row))
|
||||
for row in cursor.fetchall()
|
||||
]
|
||||
table=[]
|
||||
table.append([col[0] for col in desc])
|
||||
table = table + cursor.fetchall()
|
||||
print "Table: " + str(table)
|
||||
return table
|
||||
|
||||
def SQL_query_to_list(cursor, query_string):
|
||||
cursor.execute(query_string)
|
||||
raw_result=dictfetchall(cursor)
|
||||
print raw_result
|
||||
return raw_result
|
||||
|
||||
def dashboard(request):
|
||||
"""
|
||||
Quick hack to show staff enrollment numbers. This should be
|
||||
replaced with a real dashboard later. This version is a short-term
|
||||
bandaid for the next couple weeks.
|
||||
Slightly less hackish hack to show staff enrollment numbers and other
|
||||
simple queries.
|
||||
|
||||
All queries here should be indexed and simple. Mostly, this means don't
|
||||
touch courseware_studentmodule, as tempting as it may be.
|
||||
|
||||
"""
|
||||
if not request.user.is_staff:
|
||||
raise Http404
|
||||
|
||||
queries = []
|
||||
queries.append("select count(user_id) as students, course_id from student_courseenrollment group by course_id order by students desc;")
|
||||
queries.append("select count(distinct user_id) as unique_students from student_courseenrollment;")
|
||||
queries.append("select registrations, count(registrations) from (select count(user_id) as registrations from student_courseenrollment group by user_id) as registrations_per_user group by registrations;")
|
||||
# results are passed to the template. The template knows how to render
|
||||
# two types of results: scalars and tables. Scalars should be represented
|
||||
# as "Visible Title": Value and tables should be lists of lists where each
|
||||
# inner list represents a single row of the table
|
||||
results = {"scalars":{},"tables":{}}
|
||||
|
||||
# count how many users we have
|
||||
results["scalars"]["Unique Usernames"]=User.objects.filter().count()
|
||||
results["scalars"]["Activated Usernames"]=User.objects.filter(is_active=1).count()
|
||||
|
||||
# count how many enrollments we have
|
||||
results["scalars"]["Total Enrollments Across All Courses"]=CourseEnrollment.objects.count()
|
||||
|
||||
# establish a direct connection to the database (for executing raw SQL)
|
||||
from django.db import connection
|
||||
cursor = connection.cursor()
|
||||
results = []
|
||||
|
||||
for query in queries:
|
||||
cursor.execute(query)
|
||||
results.append(dictfetchall(cursor))
|
||||
# define the queries that will generate our user-facing tables
|
||||
# table queries need not take the form of raw SQL, but do in this case since
|
||||
# the MySQL backend for django isn't very friendly with group by or distinct
|
||||
table_queries = {}
|
||||
table_queries["course enrollments"]= \
|
||||
"select "+ \
|
||||
"course_id as Course, "+ \
|
||||
"count(user_id) as Students " + \
|
||||
"from student_courseenrollment "+ \
|
||||
"group by course_id "+ \
|
||||
"order by students desc;"
|
||||
table_queries["number of students in each number of classes"]= \
|
||||
"select registrations as 'Registered for __ Classes' , "+ \
|
||||
"count(registrations) as Users "+ \
|
||||
"from (select count(user_id) as registrations "+ \
|
||||
"from student_courseenrollment "+ \
|
||||
"group by user_id) as registrations_per_user "+ \
|
||||
"group by registrations;"
|
||||
|
||||
return HttpResponse(json.dumps(results, indent=4))
|
||||
# add the result for each of the table_queries to the results object
|
||||
for query in table_queries.keys():
|
||||
cursor.execute(table_queries[query])
|
||||
results["tables"][query] = SQL_query_to_list(cursor, table_queries[query])
|
||||
|
||||
context={"results":results}
|
||||
|
||||
return render_to_response("admin_dashboard.html",context)
|
||||
|
||||
44
lms/templates/admin_dashboard.html
Normal file
44
lms/templates/admin_dashboard.html
Normal file
@@ -0,0 +1,44 @@
|
||||
<%namespace name='static' file='static_content.html'/>
|
||||
|
||||
<%inherit file="main.html" />
|
||||
|
||||
<section class="container about">
|
||||
|
||||
<section class="basic_stats">
|
||||
|
||||
<div class="edx_summary">
|
||||
<h2>edX-wide Summary</h2>
|
||||
<table style="margin-left:auto;margin-right:auto;width:50%">
|
||||
% for key in results["scalars"]:
|
||||
<tr>
|
||||
<td>${key}</td>
|
||||
<td>${results["scalars"][key]}</td>
|
||||
</tr>
|
||||
% endfor
|
||||
</table>
|
||||
</div>
|
||||
|
||||
% for table in results["tables"]:
|
||||
<br/>
|
||||
<div class="table_display">
|
||||
<h2>${table}</h2>
|
||||
<table style="margin-left:auto;margin-right:auto;width:50%">
|
||||
<tr>
|
||||
% for column in results["tables"][table][0]:
|
||||
<td><b>${column}</b></td>
|
||||
% endfor
|
||||
</tr>
|
||||
% for row in results["tables"][table][1:]:
|
||||
<tr>
|
||||
% for column in row:
|
||||
<td>${column}</td>
|
||||
% endfor
|
||||
</tr>
|
||||
% endfor
|
||||
</table>
|
||||
|
||||
</div>
|
||||
% endfor
|
||||
</section>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user