diff --git a/README.md b/README.md index 25663ffb..dab5a028 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Requirements 1. python-mysqldb 1. django 3.0 1. libldap2-dev +1. libmysqlclient-dev ``` #### Installation @@ -34,7 +35,7 @@ chmod +x setup.sh Installation of Requirements ```bash -sudo apt install apache2 mysql-server python python3-pip python-mysqldb libldap2-dev +sudo apt install apache2 mysql-server python python3-pip python-mysqldb libldap2-dev libmysqlclient-dev sudo python3 -m pip install -r requirements.txt ``` @@ -62,7 +63,7 @@ DATABASES = { ```bash python3 manage.py makemigrations python3 manage.py migrate -python3 manage.py runserver 127.0.0.1:8000 +python3 manage.py runserver 127.0.0.1:8090 ``` 1. Open "http://127.0.0.1:8090" in your browser. diff --git a/course/filters.py b/course/filters.py index eb46e5c3..86f44e99 100644 --- a/course/filters.py +++ b/course/filters.py @@ -39,40 +39,87 @@ class Meta: class LevelFilter(django_filters.FilterSet): + institute_id = django_filters.ModelChoiceFilter( + field_name="institute", + lookup_expr="exact", + empty_label="Select Institute", + queryset=Institute.objects.all(), + ) + class Meta: model = Level fields = {"level_name": ["icontains"]} class ProgrammeFilter(django_filters.FilterSet): + level_id = django_filters.ModelChoiceFilter( + field_name="level", + lookup_expr="exact", + empty_label="Select Level", + queryset=Level.objects.all(), + ) + class Meta: model = Programme fields = {"programme_code": ["exact"], "programme_name": ["icontains"]} class DisciplineFilter(django_filters.FilterSet): + department_code = django_filters.ModelChoiceFilter( + field_name="department", + lookup_expr="exact", + empty_label="Select Department", + queryset=Department.objects.all(), + ) + programme_code = django_filters.ModelChoiceFilter( + field_name="programme", + lookup_expr="exact", + empty_label="Select Programme", + queryset=Programme.objects.all(), + ) + class Meta: model = Discipline fields = { "discipline_code": ["exact"], "discipline_name": ["icontains"], - "department__department_name": ["icontains"], } class CourseFilter(django_filters.FilterSet): + discipline_code = django_filters.ModelChoiceFilter( + field_name="discipline", + lookup_expr="exact", + empty_label="Select Discipline", + queryset=Discipline.objects.all(), + ) + class Meta: model = Course fields = {"course_id": ["exact"], "course_title": ["icontains"]} class ModuleFilter(django_filters.FilterSet): + course_id = django_filters.ModelChoiceFilter( + field_name="course", + lookup_expr="exact", + empty_label="Select Course", + queryset=Course.objects.all(), + ) + class Meta: model = Module fields = {"module_title": ["icontains"]} class UnitFilter(django_filters.FilterSet): + module_id = django_filters.ModelChoiceFilter( + field_name="module", + lookup_expr="exact", + empty_label="Select Module", + queryset=Module.objects.all(), + ) + class Meta: model = Unit fields = {"unit_name": ["icontains"]} diff --git a/course/tables.py b/course/tables.py index b8edff75..1b8071a4 100644 --- a/course/tables.py +++ b/course/tables.py @@ -1,6 +1,7 @@ from django.urls import reverse from django.utils.safestring import mark_safe import django_tables2 as tables +import bootstrap4.templatetags.bootstrap4 as bootstrap from .models import * @@ -72,6 +73,7 @@ class InstituteTable(tables.Table): edit = tables.Column( verbose_name="Edit Institute", accessor=tables.A("institute_id"), + attrs={"td": {"align": "center"}}, orderable=False, exclude_from_export=True, ) @@ -86,22 +88,39 @@ def before_render(self, request): if self.request.user.is_authenticated == False: self.columns.hide("edit") + def render_institute_name(self, value): + institute_id = Institute.objects.get(institute_name=value).institute_id + url = (reverse("level") + "?institute_id=%s") % (institute_id,) + return mark_safe( + bootstrap.bootstrap_button( + content=value, + href=url, + button_class="btn-link", + extra_classes="text-body", + ) + ) + def render_edit(self, value): url = reverse("edit-institute", args=[value]) - return mark_safe('Edit' % (url,)) + return mark_safe( + bootstrap.bootstrap_button( + content="Edit", href=url, button_class="btn-link" + ) + ) class LevelTable(tables.Table): edit = tables.Column( verbose_name="Edit Level", accessor=tables.A("level_id"), + attrs={"td": {"align": "center"}}, orderable=False, exclude_from_export=True, ) class Meta: model = Level - fields = ("level_name", "level_short_name") + fields = ("level_name", "level_short_name", "institute") attrs = {"class": "table-striped table-bordered"} empty_text = "There is no level matching the search criteria..." @@ -109,15 +128,32 @@ def before_render(self, request): if self.request.user.is_authenticated == False: self.columns.hide("edit") + def render_level_name(self, value): + level_id = Level.objects.get(level_name=value).level_id + url = (reverse("programme") + "?level_id=%s") % (level_id,) + return mark_safe( + bootstrap.bootstrap_button( + content=value, + href=url, + button_class="btn-link", + extra_classes="text-body", + ) + ) + def render_edit(self, value): url = reverse("edit-level", args=[value]) - return mark_safe('Edit' % (url,)) + return mark_safe( + bootstrap.bootstrap_button( + content="Edit", href=url, button_class="btn-link" + ) + ) class ProgrammeTable(tables.Table): edit = tables.Column( verbose_name="Edit Programme", accessor=tables.A("programme_code"), + attrs={"td": {"align": "center"}}, orderable=False, exclude_from_export=True, ) @@ -129,6 +165,7 @@ class Meta: "programme_name", "programme_short_name", "programme_fees", + "level", ) attrs = {"class": "table-striped table-bordered"} empty_text = "There is no programme matching the search criteria..." @@ -137,15 +174,34 @@ def before_render(self, request): if self.request.user.is_authenticated == False: self.columns.hide("edit") + def render_programme_name(self, value): + programme_code = Programme.objects.get( + programme_name=value + ).programme_code + url = (reverse("discipline") + "?programme_code=%s") % (programme_code,) + return mark_safe( + bootstrap.bootstrap_button( + content=value, + href=url, + button_class="btn-link", + extra_classes="text-body", + ) + ) + def render_edit(self, value): url = reverse("edit-programme", args=[value]) - return mark_safe('Edit' % (url,)) + return mark_safe( + bootstrap.bootstrap_button( + content="Edit", href=url, button_class="btn-link" + ) + ) class DepartmentTable(tables.Table): edit = tables.Column( verbose_name="Edit Department", accessor=tables.A("department_code"), + attrs={"td": {"align": "center"}}, orderable=False, exclude_from_export=True, ) @@ -162,13 +218,18 @@ def before_render(self, request): def render_edit(self, value): url = reverse("edit-department", args=[value]) - return mark_safe('Edit' % (url,)) + return mark_safe( + bootstrap.bootstrap_button( + content="Edit", href=url, button_class="btn-link" + ) + ) class DisciplineTable(tables.Table): edit = tables.Column( verbose_name="Edit Discipline", accessor=tables.A("discipline_code"), + attrs={"td": {"align": "center"}}, orderable=False, exclude_from_export=True, ) @@ -181,6 +242,7 @@ class Meta: "discipline_short_name", "total_credits", "department", + "programme", ) attrs = {"class": "table-striped table-bordered"} empty_text = "There is no discipline matching the search criteria..." @@ -189,15 +251,34 @@ def before_render(self, request): if self.request.user.is_authenticated == False: self.columns.hide("edit") + def render_discipline_name(self, value): + discipline_code = Discipline.objects.get( + discipline_name=value + ).discipline_code + url = (reverse("course") + "?discipline_code=%s") % (discipline_code,) + return mark_safe( + bootstrap.bootstrap_button( + content=value, + href=url, + button_class="btn-link", + extra_classes="text-body", + ) + ) + def render_edit(self, value): url = reverse("edit-discipline", args=[value]) - return mark_safe('Edit' % (url,)) + return mark_safe( + bootstrap.bootstrap_button( + content="Edit", href=url, button_class="btn-link" + ) + ) class CourseTable(tables.Table): edit = tables.Column( verbose_name="Edit Course", accessor=tables.A("course_id"), + attrs={"td": {"align": "center"}}, orderable=False, exclude_from_export=True, ) @@ -217,6 +298,7 @@ class Meta: "practical_contact_hours_per_week", "course_resources", "course_test", + "discipline", ) attrs = {"class": "table-striped table-bordered"} empty_text = "There is no course matching the search criteria..." @@ -225,15 +307,32 @@ def before_render(self, request): if self.request.user.is_authenticated == False: self.columns.hide("edit") + def render_course_title(self, value): + course_id = Course.objects.get(course_title=value).course_id + url = (reverse("module") + "?course_id=%s") % (course_id,) + return mark_safe( + bootstrap.bootstrap_button( + content=value, + href=url, + button_class="btn-link", + extra_classes="text-body", + ) + ) + def render_edit(self, value): url = reverse("edit-course", args=[value]) - return mark_safe('Edit' % (url,)) + return mark_safe( + bootstrap.bootstrap_button( + content="Edit", href=url, button_class="btn-link" + ) + ) class ModuleTable(tables.Table): edit = tables.Column( verbose_name="Edit Module", accessor=tables.A("module_id"), + attrs={"td": {"align": "center"}}, orderable=False, exclude_from_export=True, ) @@ -249,6 +348,7 @@ class Meta: "module_body", "module_resources", "module_test", + "course", ) attrs = {"class": "table-striped table-bordered"} empty_text = "There is no module matching the search criteria..." @@ -257,15 +357,32 @@ def before_render(self, request): if self.request.user.is_authenticated == False: self.columns.hide("edit") + def render_module_title(self, value): + module_id = Module.objects.get(module_title=value).module_id + url = (reverse("unit") + "?module_id=%s") % (module_id,) + return mark_safe( + bootstrap.bootstrap_button( + content=value, + href=url, + button_class="btn-link", + extra_classes="text-body", + ) + ) + def render_edit(self, value): url = reverse("edit-module", args=[value]) - return mark_safe('Edit' % (url,)) + return mark_safe( + bootstrap.bootstrap_button( + content="Edit", href=url, button_class="btn-link" + ) + ) class UnitTable(tables.Table): edit = tables.Column( verbose_name="Edit Unit", accessor=tables.A("unit_number"), + attrs={"td": {"align": "center"}}, orderable=False, exclude_from_export=True, ) @@ -281,6 +398,7 @@ class Meta: "unit_body", "unit_resources", "unit_test", + "module", ) attrs = {"class": "table-striped table-bordered"} empty_text = "There is no unit matching the search criteria..." @@ -291,4 +409,8 @@ def before_render(self, request): def render_edit(self, value): url = reverse("edit-unit", args=[value]) - return mark_safe('Edit' % (url,)) + return mark_safe( + bootstrap.bootstrap_button( + content="Edit", href=url, button_class="btn-link" + ) + ) diff --git a/course/urls.py b/course/urls.py index 94b3388a..0f43c210 100644 --- a/course/urls.py +++ b/course/urls.py @@ -3,7 +3,7 @@ from django.contrib.auth.decorators import login_required urlpatterns = [ - path("", home_page), + path("", home_page, name="home"), path( "cognitive-level/", CognitiveLevelView.as_view(), name="cognitive-level" ), diff --git a/requirements.txt b/requirements.txt index cf4ff8f5..2549be92 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,12 @@ black==19.10b0 -Django==3.0 +Django==3.0.1 django-auth-ldap==2.1.0 django-bootstrap4==1.1.1 django-crispy-forms==1.8.1 +django-filter==2.2.0 django-money==1.0 django-tables2==2.2.1 martor==1.4.4 mysqlclient==1.4.6 pre-commit==1.20.0 +python-ldap==3.2.0