Add select course upon student bulk import, search field for students

This commit is contained in:
2025-11-27 11:52:25 +01:00
parent 18d2604121
commit 97b14ae1d7
5 changed files with 54 additions and 12 deletions

View File

@@ -9,8 +9,7 @@ from .models.weekpref import WeekPreference
from .admins.course_adm import CourseAdmin
from .admins.student_adm import StudentAdmin
from .admins.mission_adm import MissionProfileAdmin
from .admins.weekpred_adm import WeekPreferenceAdmin
#from .admins.hourbuilding_adm import HourBuilding, HourBuildingInLine
from .admins.weekpref_adm import WeekPreferenceAdmin
from django.contrib.admin import AdminSite

View File

@@ -34,6 +34,6 @@ class MissionProfileResource(ModelResource):
fields = ("mtype", "mnum", "duration")
import_id_fields = ("mtype", "mnum")
class MissionProfileAdmin(ImportMixin, AdminActionFormsMixin, admin.ModelAdmin):
class MissionProfileAdmin(AdminActionFormsMixin, ImportMixin, admin.ModelAdmin):
list_display = ("mtype", "mnum", "notes")
list_filter = ("mtype",)

View File

@@ -6,16 +6,25 @@ from django.utils.safestring import SafeText
from import_export import fields
from import_export.admin import ImportMixin
from import_export.tmp_storages import CacheStorage
from import_export.resources import ModelResource
from import_export.widgets import CharWidget
from import_export.forms import ConfirmImportForm, ImportForm
from django_admin_action_forms import AdminActionFormsMixin, AdminActionForm, action_with_form
from typing import Any, Dict
from ..models.courses import Course
from ..models.students import Student
from ..custom.colortag import course_color
# Custom import form to select a course for student input
class StudentCustomConfirmImportForm(ConfirmImportForm):
course = forms.ModelChoiceField(
queryset=Course.objects.all(),
required=False)
# Resource Class for Student data import
class StudentResource(ModelResource):
surname = fields.Field(attribute="surname", column_name="surname")
@@ -24,29 +33,38 @@ class StudentResource(ModelResource):
phone = fields.Field(attribute="phone", column_name="phone")
# Cleanup fields before entering
def before_import_row(self, row: dict[str, str], **kwargs) -> None:
row["name"] = SafeText(row["name"].capitalize().strip())
row["surname"] = SafeText(row["surname"].capitalize().strip())
def before_import_row(self, row: Dict[str, str], **kwargs) -> None:
row["name"] = SafeText("-".join(c.capitalize() for c in row["name"].split(" ")).strip())
row["surname"] = SafeText("-".join(c.capitalize() for c in row["surname"].split(" ")).strip())
row["phone"] = SafeText(row["phone"].replace(" ",""))
row["email"] = SafeText(row["email"].lower().strip())
return super().before_import_row(row, **kwargs)
# If course was addedd as a form kwasrg add it to the student after creation
def after_init_instance(self, instance: Student, new: bool, row: Dict[str, str], **kwargs: Dict[str, Any]):
if hasattr(kwargs, "course") and isinstance(kwargs["course"], Course):
instance.course = kwargs["course"]
class Meta:
model = Student
skip_unchanged = True
report_skipped = True
fields = ("surname", "name", "email", "phone")
import_id_fields = ("email", "phone")
fields = ("surname", "name", "email", "phone",)
import_id_fields = ("email", "phone",)
# Form Class for Student course change
class ChangeCourseForm(AdminActionForm):
course = forms.ModelChoiceField(queryset=Course.objects.all())
class StudentAdmin(ImportMixin, AdminActionFormsMixin, admin.ModelAdmin):
list_display = ("surname", "name", "course", "course_color", "email", "phone", "password", "active")
list_filter = ("course", "active")
actions = ("change_course", "disable_students")
list_display = ("surname", "name", "course", "course_color", "email", "phone", "username", "password", "active",)
list_filter = ("course", "active",)
search_fields= ("surname", "name", "phone", "email",)
actions = ("change_course", "disable_students",)
resource_classes = [StudentResource]
confirm_form_class = StudentCustomConfirmImportForm
tmp_storage_class = CacheStorage
skip_admin_log = True
@admin.display(description="Color")
def course_color(self, obj: Student) -> SafeText:
@@ -58,6 +76,10 @@ class StudentAdmin(ImportMixin, AdminActionFormsMixin, admin.ModelAdmin):
def password(self, obj: Student) -> SafeText:
return SafeText(obj.default_password())
@admin.display(description="Username")
def username(self, obj: Student) -> SafeText:
return SafeText(obj.default_username())
@admin.action(description="Deactivate Students")
def disable_students(self, request: HttpRequest, queryset: QuerySet[Student]):
for q in queryset.all():
@@ -73,3 +95,18 @@ class StudentAdmin(ImportMixin, AdminActionFormsMixin, admin.ModelAdmin):
course = data["course"]
count: int = queryset.update(course=course)
messages.success(request, f"{count} students updated to {course}")
# Return the initial form for import confirmations, request course to user
def get_confirm_form_initial(self, request: HttpRequest, import_form):
initial = super().get_confirm_form_initial(request, import_form)
if import_form and hasattr(import_form.cleaned_data, "course"):
course: Course = import_form.cleaned_data["course"]
initial["course"] = course.id
return initial
# Add course to import form kwargs to be used by resource to associate course with all imported students
def get_import_data_kwargs(self, request: HttpRequest, *args, **kwargs):
form: ImportForm | None = kwargs.get("form", None)
if form and hasattr(form, "cleaned_data"):
kwargs["course"] = form.cleaned_data.get("course", None)
return kwargs

View File

@@ -48,6 +48,12 @@ class Student(models.Model):
def default_password(self) -> str:
return f"{self.name.lower()[0]}{self.surname.lower()}{self.id}"
def default_username(self) -> str:
if self.pk and self.user:
return self.user.username
else:
return ""
# Override save method to add user for login upon Student creation
def save(self, *args, **kwargs):