-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a766b7f
commit 8b06309
Showing
7 changed files
with
246 additions
and
213 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,212 +1 @@ | ||
from django import forms | ||
from django.contrib import admin | ||
from unfold.admin import ModelAdmin, TabularInline | ||
from unfold.widgets import ( | ||
UnfoldAdminTextInputWidget, | ||
UnfoldAdminTextareaWidget, | ||
) | ||
from django.contrib import messages | ||
|
||
from .models import ( | ||
Course, | ||
Homework, | ||
Question, | ||
Project, | ||
ReviewCriteria, | ||
HomeworkState, | ||
) | ||
|
||
from .scoring import ( | ||
score_homework_submissions, | ||
update_leaderboard, | ||
fill_correct_answers, | ||
calculate_homework_statistics, | ||
) | ||
|
||
from .projects import ( | ||
assign_peer_reviews_for_project, | ||
score_project, | ||
ProjectActionStatus, | ||
) | ||
|
||
|
||
class QuestionForm(forms.ModelForm): | ||
class Meta: | ||
model = Question | ||
fields = "__all__" | ||
widgets = { | ||
"text": UnfoldAdminTextInputWidget(attrs={"size": "60"}), | ||
"possible_answers": UnfoldAdminTextareaWidget( | ||
attrs={"cols": 60, "rows": 4} | ||
), | ||
"correct_answer": UnfoldAdminTextInputWidget( | ||
attrs={"size": "20"} | ||
), | ||
} | ||
|
||
|
||
class QuestionInline(TabularInline): | ||
model = Question | ||
form = QuestionForm | ||
extra = 0 | ||
|
||
|
||
def score_selected_homeworks(modeladmin, request, queryset): | ||
for homework in queryset: | ||
status, message = score_homework_submissions(homework.id) | ||
if status: | ||
modeladmin.message_user( | ||
request, message, level=messages.SUCCESS | ||
) | ||
else: | ||
modeladmin.message_user( | ||
request, message, level=messages.WARNING | ||
) | ||
|
||
|
||
score_selected_homeworks.short_description = "Score selected homeworks" | ||
|
||
|
||
def set_most_popular_as_correct(modeladmin, request, queryset): | ||
for homework in queryset: | ||
fill_correct_answers(homework) | ||
modeladmin.message_user( | ||
request, | ||
f"Correct answer for {homework} set to most popular", | ||
level=messages.SUCCESS, | ||
) | ||
|
||
|
||
set_most_popular_as_correct.short_description = ( | ||
"Set correct answers to most popular" | ||
) | ||
|
||
|
||
def calculate_statistics_selected_homeworks( | ||
modeladmin, request, queryset | ||
): | ||
for homework in queryset: | ||
if homework.state != HomeworkState.SCORED.value: | ||
modeladmin.message_user( | ||
request, | ||
f"Cannot calculate statistics for {homework} " | ||
"because it has not been scored", | ||
level=messages.WARNING, | ||
) | ||
continue | ||
|
||
calculate_homework_statistics(homework, force=True) | ||
|
||
message = f"Statistics calculated for {homework}" | ||
modeladmin.message_user( | ||
request, message, level=messages.SUCCESS | ||
) | ||
|
||
|
||
calculate_statistics_selected_homeworks.short_description = ( | ||
"Calculate statistics" | ||
) | ||
|
||
|
||
@admin.register(Homework) | ||
class HomeworkAdmin(ModelAdmin): | ||
inlines = [QuestionInline] | ||
actions = [ | ||
score_selected_homeworks, | ||
set_most_popular_as_correct, | ||
calculate_statistics_selected_homeworks, | ||
] | ||
list_display = ["title", "course", "due_date", "state"] | ||
list_filter = ["course__slug"] | ||
|
||
|
||
class CriteriaForm(forms.ModelForm): | ||
class Meta: | ||
model = ReviewCriteria | ||
fields = "__all__" | ||
widgets = { | ||
"description": UnfoldAdminTextInputWidget( | ||
attrs={"size": "60"} | ||
), | ||
"options": UnfoldAdminTextareaWidget( | ||
attrs={"cols": 60, "rows": 4} | ||
), | ||
} | ||
|
||
|
||
class CriteriaInline(TabularInline): | ||
model = ReviewCriteria | ||
form = CriteriaForm | ||
extra = 0 | ||
|
||
|
||
def update_leaderboard_admin(modeladmin, request, queryset): | ||
for course in queryset: | ||
update_leaderboard(course) | ||
modeladmin.message_user( | ||
request, | ||
f"Leaderboard updated for course {course}", | ||
level=messages.SUCCESS, | ||
) | ||
|
||
|
||
update_leaderboard_admin.short_description = "Update leaderboard" | ||
|
||
|
||
@admin.register(Course) | ||
class CourseAdmin(ModelAdmin): | ||
actions = [update_leaderboard_admin] | ||
inlines = [CriteriaInline] | ||
list_display = ["title"] | ||
|
||
|
||
def assign_peer_reviews_for_project_admin( | ||
modeladmin, request, queryset | ||
): | ||
for project in queryset: | ||
status, message = assign_peer_reviews_for_project(project) | ||
if status == ProjectActionStatus.OK: | ||
modeladmin.message_user( | ||
request, message, level=messages.SUCCESS | ||
) | ||
else: | ||
modeladmin.message_user( | ||
request, message, level=messages.WARNING | ||
) | ||
|
||
|
||
assign_peer_reviews_for_project_admin.short_description = ( | ||
"Assign peer reviews" | ||
) | ||
|
||
|
||
def score_projects_admin(modeladmin, request, queryset): | ||
for project in queryset: | ||
status, message = score_project(project) | ||
if status == ProjectActionStatus.OK: | ||
modeladmin.message_user( | ||
request, message, level=messages.SUCCESS | ||
) | ||
else: | ||
modeladmin.message_user( | ||
request, message, level=messages.WARNING | ||
) | ||
|
||
|
||
score_projects_admin.short_description = "Score projects" | ||
|
||
|
||
@admin.register(Project) | ||
class ProjectAdmin(ModelAdmin): | ||
actions = [ | ||
assign_peer_reviews_for_project_admin, | ||
score_projects_admin, | ||
] | ||
|
||
list_display = ["title", "course", "state"] | ||
list_filter = ["course__slug"] | ||
|
||
|
||
@admin.register(ReviewCriteria) | ||
class ReviewCriteriaAdmin(ModelAdmin): | ||
pass | ||
from .admin import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from pathlib import Path | ||
from importlib import import_module | ||
|
||
|
||
def import_admin_modules(): | ||
# we just want to import all the modules, | ||
# so in admin.py we can use the star import | ||
current_dir = Path(__file__).resolve().parent | ||
|
||
for python_file in current_dir.glob("*.py"): | ||
if python_file.name == "__init__.py": | ||
continue | ||
|
||
module_name = f"courses.admin.{python_file.stem}" | ||
|
||
try: | ||
import_module(module_name) | ||
except ImportError as e: | ||
print(f"Failed to import {module_name}: {e}") | ||
|
||
|
||
import_admin_modules() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
from django import forms | ||
from django.contrib import admin | ||
from unfold.admin import ModelAdmin, TabularInline | ||
from unfold.widgets import ( | ||
UnfoldAdminTextInputWidget, | ||
UnfoldAdminTextareaWidget, | ||
) | ||
|
||
from django.contrib import messages | ||
|
||
from courses.models import Course, ReviewCriteria | ||
from courses.scoring import update_leaderboard | ||
|
||
|
||
class CriteriaForm(forms.ModelForm): | ||
class Meta: | ||
model = ReviewCriteria | ||
fields = "__all__" | ||
widgets = { | ||
"description": UnfoldAdminTextInputWidget( | ||
attrs={"size": "60"} | ||
), | ||
"options": UnfoldAdminTextareaWidget( | ||
attrs={"cols": 60, "rows": 4} | ||
), | ||
} | ||
|
||
|
||
class CriteriaInline(TabularInline): | ||
model = ReviewCriteria | ||
form = CriteriaForm | ||
extra = 0 | ||
|
||
|
||
def update_leaderboard_admin(modeladmin, request, queryset): | ||
for course in queryset: | ||
update_leaderboard(course) | ||
modeladmin.message_user( | ||
request, | ||
f"Leaderboard updated for course {course}", | ||
level=messages.SUCCESS, | ||
) | ||
|
||
|
||
update_leaderboard_admin.short_description = "Update leaderboard" | ||
|
||
|
||
@admin.register(Course) | ||
class CourseAdmin(ModelAdmin): | ||
actions = [update_leaderboard_admin] | ||
inlines = [CriteriaInline] | ||
list_display = ["title"] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
from django import forms | ||
from django.contrib import admin | ||
from unfold.admin import ModelAdmin, TabularInline | ||
from unfold.widgets import ( | ||
UnfoldAdminTextInputWidget, | ||
UnfoldAdminTextareaWidget, | ||
) | ||
from django.contrib import messages | ||
|
||
from courses.models import Homework, Question, HomeworkState | ||
|
||
from courses.scoring import ( | ||
score_homework_submissions, | ||
fill_correct_answers, | ||
calculate_homework_statistics, | ||
) | ||
|
||
|
||
class QuestionForm(forms.ModelForm): | ||
class Meta: | ||
model = Question | ||
fields = "__all__" | ||
widgets = { | ||
"text": UnfoldAdminTextInputWidget(attrs={"size": "60"}), | ||
"possible_answers": UnfoldAdminTextareaWidget( | ||
attrs={"cols": 60, "rows": 4} | ||
), | ||
"correct_answer": UnfoldAdminTextInputWidget( | ||
attrs={"size": "20"} | ||
), | ||
} | ||
|
||
|
||
class QuestionInline(TabularInline): | ||
model = Question | ||
form = QuestionForm | ||
extra = 0 | ||
|
||
|
||
def score_selected_homeworks(modeladmin, request, queryset): | ||
for homework in queryset: | ||
status, message = score_homework_submissions(homework.id) | ||
if status: | ||
modeladmin.message_user( | ||
request, message, level=messages.SUCCESS | ||
) | ||
else: | ||
modeladmin.message_user( | ||
request, message, level=messages.WARNING | ||
) | ||
|
||
|
||
score_selected_homeworks.short_description = "Score selected homeworks" | ||
|
||
|
||
def set_most_popular_as_correct(modeladmin, request, queryset): | ||
for homework in queryset: | ||
fill_correct_answers(homework) | ||
modeladmin.message_user( | ||
request, | ||
f"Correct answer for {homework} set to most popular", | ||
level=messages.SUCCESS, | ||
) | ||
|
||
|
||
set_most_popular_as_correct.short_description = ( | ||
"Set correct answers to most popular" | ||
) | ||
|
||
|
||
def calculate_statistics_selected_homeworks( | ||
modeladmin, request, queryset | ||
): | ||
for homework in queryset: | ||
if homework.state != HomeworkState.SCORED.value: | ||
modeladmin.message_user( | ||
request, | ||
f"Cannot calculate statistics for {homework} " | ||
"because it has not been scored", | ||
level=messages.WARNING, | ||
) | ||
continue | ||
|
||
calculate_homework_statistics(homework, force=True) | ||
|
||
message = f"Statistics calculated for {homework}" | ||
modeladmin.message_user( | ||
request, message, level=messages.SUCCESS | ||
) | ||
|
||
|
||
calculate_statistics_selected_homeworks.short_description = ( | ||
"Calculate statistics" | ||
) | ||
|
||
|
||
@admin.register(Homework) | ||
class HomeworkAdmin(ModelAdmin): | ||
inlines = [QuestionInline] | ||
actions = [ | ||
score_selected_homeworks, | ||
set_most_popular_as_correct, | ||
calculate_statistics_selected_homeworks, | ||
] | ||
list_display = ["title", "course", "due_date", "state"] | ||
list_filter = ["course__slug"] |
Oops, something went wrong.