Resolve lint warnings

This commit is contained in:
papi 2023-12-26 00:25:09 +03:00
parent ca47cbf8c7
commit 11154d2fd1
41 changed files with 1878 additions and 1127 deletions

View File

@ -5,13 +5,31 @@ from .models import User, Student, Parent
class UserAdmin(admin.ModelAdmin): class UserAdmin(admin.ModelAdmin):
list_display = ['get_full_name', 'username', 'email', 'is_active', 'is_student', 'is_lecturer', 'is_parent', 'is_staff'] list_display = [
search_fields = ['username', 'first_name', 'last_name', 'email', 'is_active', 'is_lecturer', 'is_parent', 'is_staff'] "get_full_name",
"username",
"email",
"is_active",
"is_student",
"is_lecturer",
"is_parent",
"is_staff",
]
search_fields = [
"username",
"first_name",
"last_name",
"email",
"is_active",
"is_lecturer",
"is_parent",
"is_staff",
]
class Meta: class Meta:
managed = True managed = True
verbose_name = 'User' verbose_name = "User"
verbose_name_plural = 'Users' verbose_name_plural = "Users"
# class ScoreAdmin(admin.ModelAdmin): # class ScoreAdmin(admin.ModelAdmin):

View File

@ -1,10 +1,8 @@
from rest_framework import serializers from rest_framework import serializers
from django.contrib.auth.views import get_user_model from django.contrib.auth import get_user_model
User = get_user_model()
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = User model = get_user_model()
fields = '__all__' fields = "__all__"

View File

@ -1,9 +1,8 @@
from . import views
from django.urls import path from django.urls import path
from . import views
app_name = "accounts-api" app_name = "accounts-api"
urlpatterns = [ urlpatterns = [
path('', views.UserListAPIView.as_view(), name="users-api"), path("", views.UserListAPIView.as_view(), name="users-api"),
] ]

View File

@ -1,24 +1,23 @@
from rest_framework import generics from rest_framework import generics
from django.contrib.auth.views import get_user_model from django.contrib.auth import get_user_model
from .serializers import UserSerializer from .serializers import UserSerializer
User = get_user_model()
class UserListAPIView(generics.ListAPIView): class UserListAPIView(generics.ListAPIView):
lookup_field = 'id' lookup_field = "id"
serializer_class = UserSerializer serializer_class = UserSerializer
def get_queryset(self): def get_queryset(self):
qs = User.objects.all() qs = get_user_model().objects.all()
q = self.request.GET.get('q') q = self.request.GET.get("q")
if q is not None: if q is not None:
qs = qs.filter(username__iexact=q) qs = qs.filter(username__iexact=q)
return qs return qs
class UserDetailView(generics.RetrieveAPIView): class UserDetailView(generics.RetrieveAPIView):
lookup_field = 'id' User = get_user_model()
lookup_field = "id"
queryset = User.objects.all() queryset = User.objects.all()
model = User model = User

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class AccountsConfig(AppConfig): class AccountsConfig(AppConfig):
name = 'accounts' name = "accounts"

View File

@ -3,7 +3,9 @@ from django.http import Http404
from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.decorators import user_passes_test
def student_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=Http404): def student_required(
function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=Http404
):
""" """
Decorator for views that checks that the logged in user is a student, Decorator for views that checks that the logged in user is a student,
redirects to the log-in page if necessary. redirects to the log-in page if necessary.
@ -11,14 +13,16 @@ def student_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, log
actual_decorator = user_passes_test( actual_decorator = user_passes_test(
lambda u: u.is_active and u.is_student or u.is_superuser, lambda u: u.is_active and u.is_student or u.is_superuser,
login_url=login_url, login_url=login_url,
redirect_field_name=redirect_field_name redirect_field_name=redirect_field_name,
) )
if function: if function:
return actual_decorator(function) return actual_decorator(function)
return actual_decorator return actual_decorator
def lecturer_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=Http404): def lecturer_required(
function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=Http404
):
""" """
Decorator for views that checks that the logged in user is a teacher, Decorator for views that checks that the logged in user is a teacher,
redirects to the log-in page if necessary. redirects to the log-in page if necessary.
@ -26,14 +30,16 @@ def lecturer_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, lo
actual_decorator = user_passes_test( actual_decorator = user_passes_test(
lambda u: u.is_active and u.is_lecturer or u.is_superuser, lambda u: u.is_active and u.is_lecturer or u.is_superuser,
login_url=login_url, login_url=login_url,
redirect_field_name=redirect_field_name redirect_field_name=redirect_field_name,
) )
if function: if function:
return actual_decorator(function) return actual_decorator(function)
return actual_decorator return actual_decorator
def admin_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=Http404): def admin_required(
function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=Http404
):
""" """
Decorator for views that checks that the logged in user is a teacher, Decorator for views that checks that the logged in user is a teacher,
redirects to the log-in page if necessary. redirects to the log-in page if necessary.
@ -41,7 +47,7 @@ def admin_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login
actual_decorator = user_passes_test( actual_decorator = user_passes_test(
lambda u: u.is_active and u.is_superuser, lambda u: u.is_active and u.is_superuser,
login_url=login_url, login_url=login_url,
redirect_field_name=redirect_field_name redirect_field_name=redirect_field_name,
) )
if function: if function:
return actual_decorator(function) return actual_decorator(function)

View File

@ -1,82 +1,59 @@
from django import forms from django import forms
from django.db import transaction from django.db import transaction
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, PasswordChangeForm from django.contrib.auth.forms import (
UserCreationForm,
UserChangeForm,
)
# from django.contrib.auth.models import User # from django.contrib.auth.models import User
from django.contrib.auth.forms import PasswordResetForm from django.contrib.auth.forms import PasswordResetForm
from course.models import Program from course.models import Program
# from .models import User, Student, LEVEL # from .models import User, Student, LEVEL
from .models import * from .models import *
class StaffAddForm(UserCreationForm): class StaffAddForm(UserCreationForm):
username = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'text', 'class': 'form-control', }),
label="Username", )
first_name = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'text', 'class': 'form-control', }),
label="First Name", )
last_name = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'text', 'class': 'form-control', }),
label="Last Name", )
address = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'text', 'class': 'form-control', }),
label="Address", )
phone = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'text', 'class': 'form-control', }),
label="Mobile No.", )
email = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'text', 'class': 'form-control', }),
label="Email", )
password1 = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'password', 'class': 'form-control', }),
label="Password", )
password2 = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'password', 'class': 'form-control', }),
label="Password Confirmation", )
class Meta(UserCreationForm.Meta):
model = User
@transaction.atomic()
def save(self, commit=True):
user = super().save(commit=False)
user.is_lecturer = True
user.first_name = self.cleaned_data.get('first_name')
user.last_name = self.cleaned_data.get('last_name')
user.phone = self.cleaned_data.get('phone')
user.address = self.cleaned_data.get('address')
user.email = self.cleaned_data.get('email')
if commit:
user.save()
return user
class StudentAddForm(UserCreationForm):
username = forms.CharField( username = forms.CharField(
max_length=30, max_length=30,
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'text', "type": "text",
'class': 'form-control', "class": "form-control",
'id': 'username_id'
} }
), ),
label="Username", label="Username",
) )
first_name = forms.CharField(
max_length=30,
widget=forms.TextInput(
attrs={
"type": "text",
"class": "form-control",
}
),
label="First Name",
)
last_name = forms.CharField(
max_length=30,
widget=forms.TextInput(
attrs={
"type": "text",
"class": "form-control",
}
),
label="Last Name",
)
address = forms.CharField( address = forms.CharField(
max_length=30, max_length=30,
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'text', "type": "text",
'class': 'form-control', "class": "form-control",
} }
), ),
label="Address", label="Address",
@ -86,8 +63,88 @@ class StudentAddForm(UserCreationForm):
max_length=30, max_length=30,
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'text', "type": "text",
'class': 'form-control', "class": "form-control",
}
),
label="Mobile No.",
)
email = forms.CharField(
max_length=30,
widget=forms.TextInput(
attrs={
"type": "text",
"class": "form-control",
}
),
label="Email",
)
password1 = forms.CharField(
max_length=30,
widget=forms.TextInput(
attrs={
"type": "password",
"class": "form-control",
}
),
label="Password",
)
password2 = forms.CharField(
max_length=30,
widget=forms.TextInput(
attrs={
"type": "password",
"class": "form-control",
}
),
label="Password Confirmation",
)
class Meta(UserCreationForm.Meta):
model = User
@transaction.atomic()
def save(self, commit=True):
user = super().save(commit=False)
user.is_lecturer = True
user.first_name = self.cleaned_data.get("first_name")
user.last_name = self.cleaned_data.get("last_name")
user.phone = self.cleaned_data.get("phone")
user.address = self.cleaned_data.get("address")
user.email = self.cleaned_data.get("email")
if commit:
user.save()
return user
class StudentAddForm(UserCreationForm):
username = forms.CharField(
max_length=30,
widget=forms.TextInput(
attrs={"type": "text", "class": "form-control", "id": "username_id"}
),
label="Username",
)
address = forms.CharField(
max_length=30,
widget=forms.TextInput(
attrs={
"type": "text",
"class": "form-control",
}
),
label="Address",
)
phone = forms.CharField(
max_length=30,
widget=forms.TextInput(
attrs={
"type": "text",
"class": "form-control",
} }
), ),
label="Mobile No.", label="Mobile No.",
@ -97,8 +154,8 @@ class StudentAddForm(UserCreationForm):
max_length=30, max_length=30,
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'text', "type": "text",
'class': 'form-control', "class": "form-control",
} }
), ),
label="First name", label="First name",
@ -108,8 +165,8 @@ class StudentAddForm(UserCreationForm):
max_length=30, max_length=30,
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'text', "type": "text",
'class': 'form-control', "class": "form-control",
} }
), ),
label="Last name", label="Last name",
@ -119,34 +176,50 @@ class StudentAddForm(UserCreationForm):
widget=forms.Select( widget=forms.Select(
choices=LEVEL, choices=LEVEL,
attrs={ attrs={
'class': 'browser-default custom-select form-control', "class": "browser-default custom-select form-control",
} },
), ),
) )
department = forms.ModelChoiceField( department = forms.ModelChoiceField(
queryset=Program.objects.all(), queryset=Program.objects.all(),
widget=forms.Select(attrs={'class': 'browser-default custom-select form-control'}), widget=forms.Select(
attrs={"class": "browser-default custom-select form-control"}
),
label="Department", label="Department",
) )
email = forms.EmailField( email = forms.EmailField(
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'email', "type": "email",
'class': 'form-control', "class": "form-control",
} }
), ),
label="Email Address", label="Email Address",
) )
password1 = forms.CharField( password1 = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'password', 'class': 'form-control', }), max_length=30,
label="Password", ) widget=forms.TextInput(
attrs={
"type": "password",
"class": "form-control",
}
),
label="Password",
)
password2 = forms.CharField( password2 = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'password', 'class': 'form-control', }), max_length=30,
label="Password Confirmation", ) widget=forms.TextInput(
attrs={
"type": "password",
"class": "form-control",
}
),
label="Password Confirmation",
)
# def validate_email(self): # def validate_email(self):
# email = self.cleaned_data['email'] # email = self.cleaned_data['email']
@ -160,16 +233,16 @@ class StudentAddForm(UserCreationForm):
def save(self): def save(self):
user = super().save(commit=False) user = super().save(commit=False)
user.is_student = True user.is_student = True
user.first_name = self.cleaned_data.get('first_name') user.first_name = self.cleaned_data.get("first_name")
user.last_name = self.cleaned_data.get('last_name') user.last_name = self.cleaned_data.get("last_name")
user.address = self.cleaned_data.get('address') user.address = self.cleaned_data.get("address")
user.phone = self.cleaned_data.get('phone') user.phone = self.cleaned_data.get("phone")
user.email = self.cleaned_data.get('email') user.email = self.cleaned_data.get("email")
user.save() user.save()
student = Student.objects.create( student = Student.objects.create(
student=user, student=user,
level=self.cleaned_data.get('level'), level=self.cleaned_data.get("level"),
department=self.cleaned_data.get('department') department=self.cleaned_data.get("department"),
) )
student.save() student.save()
return user return user
@ -177,36 +250,66 @@ class StudentAddForm(UserCreationForm):
class ProfileUpdateForm(UserChangeForm): class ProfileUpdateForm(UserChangeForm):
email = forms.EmailField( email = forms.EmailField(
widget=forms.TextInput(attrs={'type': 'email', 'class': 'form-control', }), widget=forms.TextInput(
label="Email Address", ) attrs={
"type": "email",
"class": "form-control",
}
),
label="Email Address",
)
first_name = forms.CharField( first_name = forms.CharField(
widget=forms.TextInput(attrs={'type': 'text', 'class': 'form-control', }), widget=forms.TextInput(
label="First Name", ) attrs={
"type": "text",
"class": "form-control",
}
),
label="First Name",
)
last_name = forms.CharField( last_name = forms.CharField(
widget=forms.TextInput(attrs={'type': 'text', 'class': 'form-control', }), widget=forms.TextInput(
label="Last Name", ) attrs={
"type": "text",
"class": "form-control",
}
),
label="Last Name",
)
phone = forms.CharField( phone = forms.CharField(
widget=forms.TextInput(attrs={'type': 'text', 'class': 'form-control', }), widget=forms.TextInput(
label="Phone No.", ) attrs={
"type": "text",
"class": "form-control",
}
),
label="Phone No.",
)
address = forms.CharField( address = forms.CharField(
widget=forms.TextInput(attrs={'type': 'text', 'class': 'form-control', }), widget=forms.TextInput(
label="Address / city", ) attrs={
"type": "text",
"class": "form-control",
}
),
label="Address / city",
)
class Meta: class Meta:
model = User model = User
fields = ['email', 'phone', 'address', 'picture', 'first_name', 'last_name'] fields = ["email", "phone", "address", "picture", "first_name", "last_name"]
class EmailValidationOnForgotPassword(PasswordResetForm): class EmailValidationOnForgotPassword(PasswordResetForm):
def clean_email(self): def clean_email(self):
email = self.cleaned_data['email'] email = self.cleaned_data["email"]
if not User.objects.filter(email__iexact=email, is_active=True).exists(): if not User.objects.filter(email__iexact=email, is_active=True).exists():
msg = "There is no user registered with the specified E-mail address. " msg = "There is no user registered with the specified E-mail address. "
self.add_error('email', msg) self.add_error("email", msg)
return email return email
@ -215,8 +318,8 @@ class ParentAddForm(UserCreationForm):
max_length=30, max_length=30,
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'text', "type": "text",
'class': 'form-control', "class": "form-control",
} }
), ),
label="Username", label="Username",
@ -225,8 +328,8 @@ class ParentAddForm(UserCreationForm):
max_length=30, max_length=30,
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'text', "type": "text",
'class': 'form-control', "class": "form-control",
} }
), ),
label="Address", label="Address",
@ -236,8 +339,8 @@ class ParentAddForm(UserCreationForm):
max_length=30, max_length=30,
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'text', "type": "text",
'class': 'form-control', "class": "form-control",
} }
), ),
label="Mobile No.", label="Mobile No.",
@ -247,8 +350,8 @@ class ParentAddForm(UserCreationForm):
max_length=30, max_length=30,
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'text', "type": "text",
'class': 'form-control', "class": "form-control",
} }
), ),
label="First name", label="First name",
@ -258,8 +361,8 @@ class ParentAddForm(UserCreationForm):
max_length=30, max_length=30,
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'text', "type": "text",
'class': 'form-control', "class": "form-control",
} }
), ),
label="Last name", label="Last name",
@ -268,8 +371,8 @@ class ParentAddForm(UserCreationForm):
email = forms.EmailField( email = forms.EmailField(
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'email', "type": "email",
'class': 'form-control', "class": "form-control",
} }
), ),
label="Email Address", label="Email Address",
@ -277,24 +380,42 @@ class ParentAddForm(UserCreationForm):
student = forms.ModelChoiceField( student = forms.ModelChoiceField(
queryset=Student.objects.all(), queryset=Student.objects.all(),
widget=forms.Select(attrs={'class': 'browser-default custom-select form-control'}), widget=forms.Select(
attrs={"class": "browser-default custom-select form-control"}
),
label="Student", label="Student",
) )
relation_ship = forms.CharField( relation_ship = forms.CharField(
widget=forms.Select( widget=forms.Select(
choices=RELATION_SHIP, choices=RELATION_SHIP,
attrs={'class': 'browser-default custom-select form-control',} attrs={
"class": "browser-default custom-select form-control",
},
), ),
) )
password1 = forms.CharField( password1 = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'password', 'class': 'form-control', }), max_length=30,
label="Password", ) widget=forms.TextInput(
attrs={
"type": "password",
"class": "form-control",
}
),
label="Password",
)
password2 = forms.CharField( password2 = forms.CharField(
max_length=30, widget=forms.TextInput(attrs={'type': 'password', 'class': 'form-control', }), max_length=30,
label="Password Confirmation", ) widget=forms.TextInput(
attrs={
"type": "password",
"class": "form-control",
}
),
label="Password Confirmation",
)
# def validate_email(self): # def validate_email(self):
# email = self.cleaned_data['email'] # email = self.cleaned_data['email']
@ -308,16 +429,16 @@ class ParentAddForm(UserCreationForm):
def save(self): def save(self):
user = super().save(commit=False) user = super().save(commit=False)
user.is_parent = True user.is_parent = True
user.first_name = self.cleaned_data.get('first_name') user.first_name = self.cleaned_data.get("first_name")
user.last_name = self.cleaned_data.get('last_name') user.last_name = self.cleaned_data.get("last_name")
user.address = self.cleaned_data.get('address') user.address = self.cleaned_data.get("address")
user.phone = self.cleaned_data.get('phone') user.phone = self.cleaned_data.get("phone")
user.email = self.cleaned_data.get('email') user.email = self.cleaned_data.get("email")
user.save() user.save()
parent = Parent.objects.create( parent = Parent.objects.create(
user=user, user=user,
student=self.cleaned_data.get('student'), student=self.cleaned_data.get("student"),
relation_ship=self.cleaned_data.get('relation_ship') relation_ship=self.cleaned_data.get("relation_ship"),
) )
parent.save() parent.save()
return user return user

View File

@ -28,7 +28,7 @@ GRAND_MOTHER = "Grand mother"
GRAND_FATHER = "Grand father" GRAND_FATHER = "Grand father"
OTHER = "Other" OTHER = "Other"
RELATION_SHIP = ( RELATION_SHIP = (
(FATHER, "Father"), (FATHER, "Father"),
(MOTHER, "Mother"), (MOTHER, "Mother"),
(BROTHER, "Brother"), (BROTHER, "Brother"),
@ -38,16 +38,20 @@ RELATION_SHIP = (
(OTHER, "Other"), (OTHER, "Other"),
) )
class UserManager(UserManager): class UserManager(UserManager):
def search(self, query=None): def search(self, query=None):
qs = self.get_queryset() qs = self.get_queryset()
if query is not None: if query is not None:
or_lookup = (Q(username__icontains=query) | or_lookup = (
Q(first_name__icontains=query)| Q(username__icontains=query)
Q(last_name__icontains=query)| | Q(first_name__icontains=query)
Q(email__icontains=query) | Q(last_name__icontains=query)
) | Q(email__icontains=query)
qs = qs.filter(or_lookup).distinct() # distinct() is often necessary with Q lookups )
qs = qs.filter(
or_lookup
).distinct() # distinct() is often necessary with Q lookups
return qs return qs
@ -58,7 +62,9 @@ class User(AbstractUser):
is_dep_head = models.BooleanField(default=False) is_dep_head = models.BooleanField(default=False)
phone = models.CharField(max_length=60, blank=True, null=True) phone = models.CharField(max_length=60, blank=True, null=True)
address = models.CharField(max_length=60, blank=True, null=True) address = models.CharField(max_length=60, blank=True, null=True)
picture = models.ImageField(upload_to='profile_pictures/%y/%m/%d/', default='default.png', null=True) picture = models.ImageField(
upload_to="profile_pictures/%y/%m/%d/", default="default.png", null=True
)
email = models.EmailField(blank=True, null=True) email = models.EmailField(blank=True, null=True)
username_validator = ASCIIUsernameValidator() username_validator = ASCIIUsernameValidator()
@ -73,7 +79,7 @@ class User(AbstractUser):
return full_name return full_name
def __str__(self): def __str__(self):
return '{} ({})'.format(self.username, self.get_full_name) return "{} ({})".format(self.username, self.get_full_name)
@property @property
def get_user_role(self): def get_user_role(self):
@ -90,11 +96,11 @@ class User(AbstractUser):
try: try:
return self.picture.url return self.picture.url
except: except:
no_picture = settings.MEDIA_URL + 'default.png' no_picture = settings.MEDIA_URL + "default.png"
return no_picture return no_picture
def get_absolute_url(self): def get_absolute_url(self):
return reverse('profile_single', kwargs={'id': self.id}) return reverse("profile_single", kwargs={"id": self.id})
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
super().save(*args, **kwargs) super().save(*args, **kwargs)
@ -108,7 +114,7 @@ class User(AbstractUser):
pass pass
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
if self.picture.url != settings.MEDIA_URL + 'default.png': if self.picture.url != settings.MEDIA_URL + "default.png":
self.picture.delete() self.picture.delete()
super().delete(*args, **kwargs) super().delete(*args, **kwargs)
@ -117,10 +123,10 @@ class StudentManager(models.Manager):
def search(self, query=None): def search(self, query=None):
qs = self.get_queryset() qs = self.get_queryset()
if query is not None: if query is not None:
or_lookup = (Q(level__icontains=query) | or_lookup = Q(level__icontains=query) | Q(department__icontains=query)
Q(department__icontains=query) qs = qs.filter(
) or_lookup
qs = qs.filter(or_lookup).distinct() # distinct() is often necessary with Q lookups ).distinct() # distinct() is often necessary with Q lookups
return qs return qs
@ -136,7 +142,7 @@ class Student(models.Model):
return self.student.get_full_name return self.student.get_full_name
def get_absolute_url(self): def get_absolute_url(self):
return reverse('profile_single', kwargs={'id': self.id}) return reverse("profile_single", kwargs={"id": self.id})
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
self.student.delete() self.student.delete()
@ -145,9 +151,10 @@ class Student(models.Model):
class Parent(models.Model): class Parent(models.Model):
""" """
Connect student with their parent, parents can Connect student with their parent, parents can
only view their connected students information only view their connected students information
""" """
user = models.OneToOneField(User, on_delete=models.CASCADE) user = models.OneToOneField(User, on_delete=models.CASCADE)
student = models.OneToOneField(Student, null=True, on_delete=models.SET_NULL) student = models.OneToOneField(Student, null=True, on_delete=models.SET_NULL)
first_name = models.CharField(max_length=120) first_name = models.CharField(max_length=120)

View File

@ -1,57 +1,59 @@
from django.urls import path, include from django.urls import path, include
from django.contrib.auth.views import ( from django.contrib.auth.views import (
PasswordResetView, PasswordResetDoneView, PasswordResetConfirmView, PasswordResetView,
PasswordResetCompleteView, LoginView, LogoutView PasswordResetDoneView,
) PasswordResetConfirmView,
PasswordResetCompleteView,
LoginView,
LogoutView,
)
from .views import ( from .views import (
profile, profile_single, admin_panel, profile,
profile_update, change_password, profile_single,
LecturerListView, StudentListView, admin_panel,
staff_add_view, edit_staff, profile_update,
delete_staff, student_add_view, change_password,
edit_student, delete_student, ParentAdd, validate_username, register LecturerListView,
) StudentListView,
staff_add_view,
edit_staff,
delete_staff,
student_add_view,
edit_student,
delete_student,
ParentAdd,
validate_username,
register,
)
from .forms import EmailValidationOnForgotPassword from .forms import EmailValidationOnForgotPassword
urlpatterns = [ urlpatterns = [
path('', include('django.contrib.auth.urls')), path("", include("django.contrib.auth.urls")),
path("admin_panel/", admin_panel, name="admin_panel"),
path('admin_panel/', admin_panel, name='admin_panel'), path("profile/", profile, name="profile"),
path("profile/<int:id>/detail/", profile_single, name="profile_single"),
path('profile/', profile, name='profile'), path("setting/", profile_update, name="edit_profile"),
path('profile/<int:id>/detail/', profile_single, name='profile_single'), path("change_password/", change_password, name="change_password"),
path('setting/', profile_update, name='edit_profile'), path("lecturers/", LecturerListView.as_view(), name="lecturer_list"),
path('change_password/', change_password, name='change_password'), path("lecturer/add/", staff_add_view, name="add_lecturer"),
path("staff/<int:pk>/edit/", edit_staff, name="staff_edit"),
path('lecturers/', LecturerListView.as_view(), name='lecturer_list'), path("lecturers/<int:pk>/delete/", delete_staff, name="lecturer_delete"),
path('lecturer/add/', staff_add_view, name='add_lecturer'), path("students/", StudentListView.as_view(), name="student_list"),
path('staff/<int:pk>/edit/', edit_staff, name='staff_edit'), path("student/add/", student_add_view, name="add_student"),
path('lecturers/<int:pk>/delete/', delete_staff, name='lecturer_delete'), path("student/<int:pk>/edit/", edit_student, name="student_edit"),
path("students/<int:pk>/delete/", delete_student, name="student_delete"),
path('students/', StudentListView.as_view(), name='student_list'), path("parents/add/", ParentAdd.as_view(), name="add_parent"),
path('student/add/', student_add_view, name='add_student'), path("ajax/validate-username/", validate_username, name="validate_username"),
path('student/<int:pk>/edit/', edit_student, name='student_edit'), path("register/", register, name="register"),
path('students/<int:pk>/delete/', delete_student, name='student_delete'),
path('parents/add/', ParentAdd.as_view(), name='add_parent'),
path('ajax/validate-username/', validate_username, name='validate_username'),
path('register/', register, name='register'),
# path('add-student/', StudentAddView.as_view(), name='add_student'), # path('add-student/', StudentAddView.as_view(), name='add_student'),
# path('programs/course/delete/<int:pk>/', course_delete, name='delete_course'), # path('programs/course/delete/<int:pk>/', course_delete, name='delete_course'),
# Setting urls # Setting urls
# path('profile/<int:pk>/edit/', profileUpdateView, name='edit_profile'), # path('profile/<int:pk>/edit/', profileUpdateView, name='edit_profile'),
# path('profile/<int:pk>/change-password/', changePasswordView, name='change_password'), # path('profile/<int:pk>/change-password/', changePasswordView, name='change_password'),
# ################################################################ # ################################################################
# path('login/', LoginView.as_view(), name='login'), # path('login/', LoginView.as_view(), name='login'),
# path('logout/', LogoutView.as_view(), name='logout', kwargs={'next_page': '/'}), # path('logout/', LogoutView.as_view(), name='logout', kwargs={'next_page': '/'}),
# path('password-reset/', PasswordResetView.as_view( # path('password-reset/', PasswordResetView.as_view(
# form_class=EmailValidationOnForgotPassword, # form_class=EmailValidationOnForgotPassword,
# template_name='registration/password_reset.html' # template_name='registration/password_reset.html'

View File

@ -7,9 +7,9 @@ from django.utils.translation import gettext_lazy as _
@deconstructible @deconstructible
class ASCIIUsernameValidator(validators.RegexValidator): class ASCIIUsernameValidator(validators.RegexValidator):
regex = r'^[a-zA-Z]+\/(...)\/(....)' regex = r"^[a-zA-Z]+\/(...)\/(....)"
message = _( message = _(
'Enter a valid username. This value may contain only English letters, ' "Enter a valid username. This value may contain only English letters, "
'numbers, and @/./+/-/_ characters.' "numbers, and @/./+/-/_ characters."
) )
flags = re.ASCII flags = re.ASCII

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class AppConfig(AppConfig): class AppConfig(AppConfig):
name = 'app' name = "app"

View File

@ -8,27 +8,32 @@ from .models import NewsAndEvents, Session, Semester, SEMESTER
class NewsAndEventsForm(forms.ModelForm): class NewsAndEventsForm(forms.ModelForm):
class Meta: class Meta:
model = NewsAndEvents model = NewsAndEvents
fields = ('title', 'summary', 'posted_as',) fields = (
"title",
"summary",
"posted_as",
)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['title'].widget.attrs.update({'class': 'form-control'}) self.fields["title"].widget.attrs.update({"class": "form-control"})
self.fields['summary'].widget.attrs.update({'class': 'form-control'}) self.fields["summary"].widget.attrs.update({"class": "form-control"})
self.fields['posted_as'].widget.attrs.update({'class': 'form-control'}) self.fields["posted_as"].widget.attrs.update({"class": "form-control"})
class SessionForm(forms.ModelForm): class SessionForm(forms.ModelForm):
next_session_begins = forms.DateTimeField( next_session_begins = forms.DateTimeField(
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'date', "type": "date",
} }
), ),
required=True) required=True,
)
class Meta: class Meta:
model = Session model = Session
fields = ['session', 'is_current_session', 'next_session_begins'] fields = ["session", "is_current_session", "next_session_begins"]
class SemesterForm(forms.ModelForm): class SemesterForm(forms.ModelForm):
@ -36,17 +41,17 @@ class SemesterForm(forms.ModelForm):
widget=forms.Select( widget=forms.Select(
choices=SEMESTER, choices=SEMESTER,
attrs={ attrs={
'class': 'browser-default custom-select', "class": "browser-default custom-select",
} },
), ),
label="semester", label="semester",
) )
is_current_semester = forms.CharField( is_current_semester = forms.CharField(
widget=forms.Select( widget=forms.Select(
choices=((True, 'Yes'), (False, 'No')), choices=((True, "Yes"), (False, "No")),
attrs={ attrs={
'class': 'browser-default custom-select', "class": "browser-default custom-select",
} },
), ),
label="is current semester ?", label="is current semester ?",
) )
@ -54,21 +59,22 @@ class SemesterForm(forms.ModelForm):
queryset=Session.objects.all(), queryset=Session.objects.all(),
widget=forms.Select( widget=forms.Select(
attrs={ attrs={
'class': 'browser-default custom-select', "class": "browser-default custom-select",
} }
), ),
required=True required=True,
) )
next_semester_begins = forms.DateTimeField( next_semester_begins = forms.DateTimeField(
widget=forms.TextInput( widget=forms.TextInput(
attrs={ attrs={
'type': 'date', "type": "date",
'class': 'form-control', "class": "form-control",
} }
), ),
required=True) required=True,
)
class Meta: class Meta:
model = Semester model = Semester
fields = ['semester', 'is_current_semester', 'session', 'next_semester_begins'] fields = ["semester", "is_current_semester", "session", "next_semester_begins"]

View File

@ -24,12 +24,12 @@ SEMESTER = (
class NewsAndEventsQuerySet(models.query.QuerySet): class NewsAndEventsQuerySet(models.query.QuerySet):
def search(self, query): def search(self, query):
lookups = (Q(title__icontains=query) | lookups = (
Q(summary__icontains=query) | Q(title__icontains=query)
Q(posted_as__icontains=query) | Q(summary__icontains=query)
) | Q(posted_as__icontains=query)
)
return self.filter(lookups).distinct() return self.filter(lookups).distinct()
@ -41,7 +41,9 @@ class NewsAndEventsManager(models.Manager):
return self.get_queryset() return self.get_queryset()
def get_by_id(self, id): def get_by_id(self, id):
qs = self.get_queryset().filter(id=id) # NewsAndEvents.objects == self.get_queryset() qs = self.get_queryset().filter(
id=id
) # NewsAndEvents.objects == self.get_queryset()
if qs.count() == 1: if qs.count() == 1:
return qs.first() return qs.first()
return None return None
@ -75,7 +77,9 @@ class Session(models.Model):
class Semester(models.Model): class Semester(models.Model):
semester = models.CharField(max_length=10, choices=SEMESTER, blank=True) semester = models.CharField(max_length=10, choices=SEMESTER, blank=True)
is_current_semester = models.BooleanField(default=False, blank=True, null=True) is_current_semester = models.BooleanField(default=False, blank=True, null=True)
session = models.ForeignKey(Session, on_delete=models.CASCADE, blank=True, null=True) session = models.ForeignKey(
Session, on_delete=models.CASCADE, blank=True, null=True
)
next_semester_begins = models.DateField(null=True, blank=True) next_semester_begins = models.DateField(null=True, blank=True)
def __str__(self): def __str__(self):

View File

@ -1,29 +1,35 @@
from django.urls import path from django.urls import path
from .views import ( from .views import (
home_view, post_add, edit_post, delete_post, home_view,
session_list_view, session_add_view, session_update_view, session_delete_view, post_add,
semester_list_view, semester_add_view, semester_update_view, semester_delete_view, edit_post,
dashboard_view delete_post,
) session_list_view,
session_add_view,
session_update_view,
session_delete_view,
semester_list_view,
semester_add_view,
semester_update_view,
semester_delete_view,
dashboard_view,
)
urlpatterns = [ urlpatterns = [
# Accounts url # Accounts url
path('', home_view, name='home'), path("", home_view, name="home"),
path('add_item/', post_add, name='add_item'), path("add_item/", post_add, name="add_item"),
path('item/<int:pk>/edit/', edit_post, name='edit_post'), path("item/<int:pk>/edit/", edit_post, name="edit_post"),
path('item/<int:pk>/delete/', delete_post, name='delete_post'), path("item/<int:pk>/delete/", delete_post, name="delete_post"),
path("session/", session_list_view, name="session_list"),
path('session/', session_list_view, name="session_list"), path("session/add/", session_add_view, name="add_session"),
path('session/add/', session_add_view, name="add_session"), path("session/<int:pk>/edit/", session_update_view, name="edit_session"),
path('session/<int:pk>/edit/', session_update_view, name="edit_session"), path("session/<int:pk>/delete/", session_delete_view, name="delete_session"),
path('session/<int:pk>/delete/', session_delete_view, name="delete_session"), path("semester/", semester_list_view, name="semester_list"),
path("semester/add/", semester_add_view, name="add_semester"),
path('semester/', semester_list_view, name="semester_list"), path("semester/<int:pk>/edit/", semester_update_view, name="edit_semester"),
path('semester/add/', semester_add_view, name="add_semester"), path("semester/<int:pk>/delete/", semester_delete_view, name="delete_semester"),
path('semester/<int:pk>/edit/', semester_update_view, name="edit_semester"), path("dashboard/", dashboard_view, name="dashboard"),
path('semester/<int:pk>/delete/', semester_delete_view, name="delete_semester"),
path('dashboard/', dashboard_view, name="dashboard"),
] ]

View File

@ -13,54 +13,62 @@ from .models import *
# ######################################################## # ########################################################
@login_required @login_required
def home_view(request): def home_view(request):
items = NewsAndEvents.objects.all().order_by('-updated_date') items = NewsAndEvents.objects.all().order_by("-updated_date")
context = { context = {
'title': "News & Events | DjangoSMS", "title": "News & Events | DjangoSMS",
'items': items, "items": items,
} }
return render(request, 'app/index.html', context) return render(request, "app/index.html", context)
@login_required @login_required
def post_add(request): def post_add(request):
if request.method == 'POST': if request.method == "POST":
form = NewsAndEventsForm(request.POST) form = NewsAndEventsForm(request.POST)
title = request.POST.get('title') title = request.POST.get("title")
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, (title + ' has been uploaded.')) messages.success(request, (title + " has been uploaded."))
return redirect('home') return redirect("home")
else: else:
messages.error(request, 'Please correct the error(s) below.') messages.error(request, "Please correct the error(s) below.")
else: else:
form = NewsAndEventsForm() form = NewsAndEventsForm()
return render(request, 'app/post_add.html', { return render(
'title': 'Add Post | DjangoSMS', request,
'form': form, "app/post_add.html",
}) {
"title": "Add Post | DjangoSMS",
"form": form,
},
)
@login_required @login_required
@lecturer_required @lecturer_required
def edit_post(request, pk): def edit_post(request, pk):
instance = get_object_or_404(NewsAndEvents, pk=pk) instance = get_object_or_404(NewsAndEvents, pk=pk)
if request.method == 'POST': if request.method == "POST":
form = NewsAndEventsForm(request.POST, instance=instance) form = NewsAndEventsForm(request.POST, instance=instance)
title = request.POST.get('title') title = request.POST.get("title")
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, (title + ' has been updated.')) messages.success(request, (title + " has been updated."))
return redirect('home') return redirect("home")
else: else:
messages.error(request, 'Please correct the error(s) below.') messages.error(request, "Please correct the error(s) below.")
else: else:
form = NewsAndEventsForm(instance=instance) form = NewsAndEventsForm(instance=instance)
return render(request, 'app/post_add.html', { return render(
'title': 'Edit Post | DjangoSMS', request,
'form': form, "app/post_add.html",
}) {
"title": "Edit Post | DjangoSMS",
"form": form,
},
)
@login_required @login_required
@ -69,8 +77,9 @@ def delete_post(request, pk):
post = get_object_or_404(NewsAndEvents, pk=pk) post = get_object_or_404(NewsAndEvents, pk=pk)
title = post.title title = post.title
post.delete() post.delete()
messages.success(request, (title + ' has been deleted.')) messages.success(request, (title + " has been deleted."))
return redirect('home') return redirect("home")
# ######################################################## # ########################################################
# Session # Session
@ -78,21 +87,23 @@ def delete_post(request, pk):
@login_required @login_required
@lecturer_required @lecturer_required
def session_list_view(request): def session_list_view(request):
""" Show list of all sessions """ """Show list of all sessions"""
sessions = Session.objects.all().order_by('-is_current_session', '-session') sessions = Session.objects.all().order_by("-is_current_session", "-session")
return render(request, 'app/session_list.html', {"sessions": sessions}) return render(request, "app/session_list.html", {"sessions": sessions})
@login_required @login_required
@lecturer_required @lecturer_required
def session_add_view(request): def session_add_view(request):
""" check request method, if POST we add session otherwise show empty form """ """check request method, if POST we add session otherwise show empty form"""
if request.method == 'POST': if request.method == "POST":
form = SessionForm(request.POST) form = SessionForm(request.POST)
if form.is_valid(): if form.is_valid():
data = form.data.get('is_current_session') # returns string of 'True' if the user selected Yes data = form.data.get(
"is_current_session"
) # returns string of 'True' if the user selected Yes
print(data) print(data)
if data == 'true': if data == "true":
sessions = Session.objects.all() sessions = Session.objects.all()
if sessions: if sessions:
for session in sessions: for session in sessions:
@ -105,22 +116,22 @@ def session_add_view(request):
form.save() form.save()
else: else:
form.save() form.save()
messages.success(request, 'Session added successfully. ') messages.success(request, "Session added successfully. ")
return redirect('session_list') return redirect("session_list")
else: else:
form = SessionForm() form = SessionForm()
return render(request, 'app/session_update.html', {'form': form}) return render(request, "app/session_update.html", {"form": form})
@login_required @login_required
@lecturer_required @lecturer_required
def session_update_view(request, pk): def session_update_view(request, pk):
session = Session.objects.get(pk=pk) session = Session.objects.get(pk=pk)
if request.method == 'POST': if request.method == "POST":
form = SessionForm(request.POST, instance=session) form = SessionForm(request.POST, instance=session)
data = form.data.get('is_current_session') data = form.data.get("is_current_session")
if data == 'true': if data == "true":
sessions = Session.objects.all() sessions = Session.objects.all()
if sessions: if sessions:
for session in sessions: for session in sessions:
@ -128,21 +139,21 @@ def session_update_view(request, pk):
unset = Session.objects.get(is_current_session=True) unset = Session.objects.get(is_current_session=True)
unset.is_current_session = False unset.is_current_session = False
unset.save() unset.save()
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, 'Session updated successfully. ') messages.success(request, "Session updated successfully. ")
return redirect('session_list') return redirect("session_list")
else: else:
form = SessionForm(request.POST, instance=session) form = SessionForm(request.POST, instance=session)
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, 'Session updated successfully. ') messages.success(request, "Session updated successfully. ")
return redirect('session_list') return redirect("session_list")
else: else:
form = SessionForm(instance=session) form = SessionForm(instance=session)
return render(request, 'app/session_update.html', {'form': form}) return render(request, "app/session_update.html", {"form": form})
@login_required @login_required
@ -152,11 +163,13 @@ def session_delete_view(request, pk):
if session.is_current_session: if session.is_current_session:
messages.error(request, "You cannot delete current session") messages.error(request, "You cannot delete current session")
return redirect('session_list') return redirect("session_list")
else: else:
session.delete() session.delete()
messages.success(request, "Session successfully deleted") messages.success(request, "Session successfully deleted")
return redirect('session_list') return redirect("session_list")
# ######################################################## # ########################################################
@ -166,86 +179,106 @@ def session_delete_view(request, pk):
@login_required @login_required
@lecturer_required @lecturer_required
def semester_list_view(request): def semester_list_view(request):
semesters = Semester.objects.all().order_by('-is_current_semester', '-semester') semesters = Semester.objects.all().order_by("-is_current_semester", "-semester")
return render(request, 'app/semester_list.html', {"semesters": semesters, }) return render(
request,
"app/semester_list.html",
{
"semesters": semesters,
},
)
@login_required @login_required
@lecturer_required @lecturer_required
def semester_add_view(request): def semester_add_view(request):
if request.method == 'POST': if request.method == "POST":
form = SemesterForm(request.POST) form = SemesterForm(request.POST)
if form.is_valid(): if form.is_valid():
data = form.data.get('is_current_semester') # returns string of 'True' if the user selected Yes data = form.data.get(
if data == 'True': "is_current_semester"
semester = form.data.get('semester') ) # returns string of 'True' if the user selected Yes
ss = form.data.get('session') if data == "True":
semester = form.data.get("semester")
ss = form.data.get("session")
session = Session.objects.get(pk=ss) session = Session.objects.get(pk=ss)
try: try:
if Semester.objects.get(semester=semester, session=ss): if Semester.objects.get(semester=semester, session=ss):
messages.error(request, semester + " semester in " + session.session + " session already exist") messages.error(
return redirect('add_semester') request,
semester
+ " semester in "
+ session.session
+ " session already exist",
)
return redirect("add_semester")
except: except:
semesters = Semester.objects.all() semesters = Semester.objects.all()
sessions = Session.objects.all() sessions = Session.objects.all()
if semesters: if semesters:
for semester in semesters: for semester in semesters:
if semester.is_current_semester == True: if semester.is_current_semester == True:
unset_semester = Semester.objects.get(is_current_semester=True) unset_semester = Semester.objects.get(
is_current_semester=True
)
unset_semester.is_current_semester = False unset_semester.is_current_semester = False
unset_semester.save() unset_semester.save()
for session in sessions: for session in sessions:
if session.is_current_session == True: if session.is_current_session == True:
unset_session = Session.objects.get(is_current_session=True) unset_session = Session.objects.get(
is_current_session=True
)
unset_session.is_current_session = False unset_session.is_current_session = False
unset_session.save() unset_session.save()
new_session = request.POST.get('session') new_session = request.POST.get("session")
set_session = Session.objects.get(pk=new_session) set_session = Session.objects.get(pk=new_session)
set_session.is_current_session = True set_session.is_current_session = True
set_session.save() set_session.save()
form.save() form.save()
messages.success(request, 'Semester added successfully.') messages.success(request, "Semester added successfully.")
return redirect('semester_list') return redirect("semester_list")
form.save() form.save()
messages.success(request, 'Semester added successfully. ') messages.success(request, "Semester added successfully. ")
return redirect('semester_list') return redirect("semester_list")
else: else:
form = SemesterForm() form = SemesterForm()
return render(request, 'app/semester_update.html', {'form': form}) return render(request, "app/semester_update.html", {"form": form})
@login_required @login_required
@lecturer_required @lecturer_required
def semester_update_view(request, pk): def semester_update_view(request, pk):
semester = Semester.objects.get(pk=pk) semester = Semester.objects.get(pk=pk)
if request.method == 'POST': if request.method == "POST":
if request.POST.get('is_current_semester') == 'True': # returns string of 'True' if the user selected yes for 'is current semester' if (
request.POST.get("is_current_semester") == "True"
): # returns string of 'True' if the user selected yes for 'is current semester'
unset_semester = Semester.objects.get(is_current_semester=True) unset_semester = Semester.objects.get(is_current_semester=True)
unset_semester.is_current_semester = False unset_semester.is_current_semester = False
unset_semester.save() unset_semester.save()
unset_session = Session.objects.get(is_current_session=True) unset_session = Session.objects.get(is_current_session=True)
unset_session.is_current_session = False unset_session.is_current_session = False
unset_session.save() unset_session.save()
new_session = request.POST.get('session') new_session = request.POST.get("session")
form = SemesterForm(request.POST, instance=semester) form = SemesterForm(request.POST, instance=semester)
if form.is_valid(): if form.is_valid():
set_session = Session.objects.get(pk=new_session) set_session = Session.objects.get(pk=new_session)
set_session.is_current_session = True set_session.is_current_session = True
set_session.save() set_session.save()
form.save() form.save()
messages.success(request, 'Semester updated successfully !') messages.success(request, "Semester updated successfully !")
return redirect('semester_list') return redirect("semester_list")
else: else:
form = SemesterForm(request.POST, instance=semester) form = SemesterForm(request.POST, instance=semester)
if form.is_valid(): if form.is_valid():
form.save() form.save()
return redirect('semester_list') return redirect("semester_list")
else: else:
form = SemesterForm(instance=semester) form = SemesterForm(instance=semester)
return render(request, 'app/semester_update.html', {'form': form}) return render(request, "app/semester_update.html", {"form": form})
@login_required @login_required
@ -254,11 +287,13 @@ def semester_delete_view(request, pk):
semester = get_object_or_404(Semester, pk=pk) semester = get_object_or_404(Semester, pk=pk)
if semester.is_current_semester: if semester.is_current_semester:
messages.error(request, "You cannot delete current semester") messages.error(request, "You cannot delete current semester")
return redirect('semester_list') return redirect("semester_list")
else: else:
semester.delete() semester.delete()
messages.success(request, "Semester successfully deleted") messages.success(request, "Semester successfully deleted")
return redirect('semester_list') return redirect("semester_list")
# ######################################################## # ########################################################
@ -284,7 +319,8 @@ def semester_delete_view(request, pk):
# return response # return response
@login_required @login_required
@admin_required @admin_required
def dashboard_view(request): def dashboard_view(request):
return render(request, 'app/dashboard.html') return render(request, "app/dashboard.html")

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class CourseConfig(AppConfig): class CourseConfig(AppConfig):
name = 'course' name = "course"

View File

@ -13,4 +13,4 @@ from coursemanagement.models import CourseSetting
# return actual_decorator(function) # return actual_decorator(function)
# return actual_decorator # return actual_decorator
is_calender_on = CourseSetting.objects.filter(add_drop=True).count() > 0 is_calender_on = CourseSetting.objects.filter(add_drop=True).count() > 0

View File

@ -8,98 +8,109 @@ from .models import Program, Course, CourseAllocation, Upload, UploadVideo
# User = settings.AUTH_USER_MODEL # User = settings.AUTH_USER_MODEL
class ProgramForm(forms.ModelForm): class ProgramForm(forms.ModelForm):
class Meta: class Meta:
model = Program model = Program
fields = '__all__' fields = "__all__"
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['title'].widget.attrs.update({'class': 'form-control'}) self.fields["title"].widget.attrs.update({"class": "form-control"})
self.fields['summary'].widget.attrs.update({'class': 'form-control'}) self.fields["summary"].widget.attrs.update({"class": "form-control"})
class CourseAddForm(forms.ModelForm): class CourseAddForm(forms.ModelForm):
class Meta: class Meta:
model = Course model = Course
fields = '__all__' fields = "__all__"
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['title'].widget.attrs.update({'class': 'form-control'}) self.fields["title"].widget.attrs.update({"class": "form-control"})
self.fields['code'].widget.attrs.update({'class': 'form-control'}) self.fields["code"].widget.attrs.update({"class": "form-control"})
# self.fields['courseUnit'].widget.attrs.update({'class': 'form-control'}) # self.fields['courseUnit'].widget.attrs.update({'class': 'form-control'})
self.fields['credit'].widget.attrs.update({'class': 'form-control'}) self.fields["credit"].widget.attrs.update({"class": "form-control"})
self.fields['summary'].widget.attrs.update({'class': 'form-control'}) self.fields["summary"].widget.attrs.update({"class": "form-control"})
self.fields['program'].widget.attrs.update({'class': 'form-control'}) self.fields["program"].widget.attrs.update({"class": "form-control"})
self.fields['level'].widget.attrs.update({'class': 'form-control'}) self.fields["level"].widget.attrs.update({"class": "form-control"})
self.fields['year'].widget.attrs.update({'class': 'form-control'}) self.fields["year"].widget.attrs.update({"class": "form-control"})
self.fields['semester'].widget.attrs.update({'class': 'form-control'}) self.fields["semester"].widget.attrs.update({"class": "form-control"})
class CourseAllocationForm(forms.ModelForm): class CourseAllocationForm(forms.ModelForm):
courses = forms.ModelMultipleChoiceField( courses = forms.ModelMultipleChoiceField(
queryset=Course.objects.all().order_by('level'), queryset=Course.objects.all().order_by("level"),
widget=forms.CheckboxSelectMultiple(attrs={'class': 'browser-default checkbox'}), widget=forms.CheckboxSelectMultiple(
required=True attrs={"class": "browser-default checkbox"}
),
required=True,
) )
lecturer = forms.ModelChoiceField( lecturer = forms.ModelChoiceField(
queryset=User.objects.filter(is_lecturer=True), queryset=User.objects.filter(is_lecturer=True),
widget=forms.Select(attrs={'class': 'browser-default custom-select'}), widget=forms.Select(attrs={"class": "browser-default custom-select"}),
label="lecturer", label="lecturer",
) )
class Meta: class Meta:
model = CourseAllocation model = CourseAllocation
fields = ['lecturer', 'courses'] fields = ["lecturer", "courses"]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
user = kwargs.pop('user') user = kwargs.pop("user")
super(CourseAllocationForm, self).__init__(*args, **kwargs) super(CourseAllocationForm, self).__init__(*args, **kwargs)
self.fields['lecturer'].queryset = User.objects.filter(is_lecturer=True) self.fields["lecturer"].queryset = User.objects.filter(is_lecturer=True)
class EditCourseAllocationForm(forms.ModelForm): class EditCourseAllocationForm(forms.ModelForm):
courses = forms.ModelMultipleChoiceField( courses = forms.ModelMultipleChoiceField(
queryset=Course.objects.all().order_by('level'), queryset=Course.objects.all().order_by("level"),
widget=forms.CheckboxSelectMultiple, widget=forms.CheckboxSelectMultiple,
required=True required=True,
) )
lecturer = forms.ModelChoiceField( lecturer = forms.ModelChoiceField(
queryset=User.objects.filter(is_lecturer=True), queryset=User.objects.filter(is_lecturer=True),
widget=forms.Select(attrs={'class': 'browser-default custom-select'}), widget=forms.Select(attrs={"class": "browser-default custom-select"}),
label="lecturer", label="lecturer",
) )
class Meta: class Meta:
model = CourseAllocation model = CourseAllocation
fields = ['lecturer', 'courses'] fields = ["lecturer", "courses"]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
# user = kwargs.pop('user') # user = kwargs.pop('user')
super(EditCourseAllocationForm, self).__init__(*args, **kwargs) super(EditCourseAllocationForm, self).__init__(*args, **kwargs)
self.fields['lecturer'].queryset = User.objects.filter(is_lecturer=True) self.fields["lecturer"].queryset = User.objects.filter(is_lecturer=True)
# Upload files to specific course # Upload files to specific course
class UploadFormFile(forms.ModelForm): class UploadFormFile(forms.ModelForm):
class Meta: class Meta:
model = Upload model = Upload
fields = ('title', 'file', 'course',) fields = (
"title",
"file",
"course",
)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['title'].widget.attrs.update({'class': 'form-control'}) self.fields["title"].widget.attrs.update({"class": "form-control"})
self.fields['file'].widget.attrs.update({'class': 'form-control'}) self.fields["file"].widget.attrs.update({"class": "form-control"})
# Upload video to specific course # Upload video to specific course
class UploadFormVideo(forms.ModelForm): class UploadFormVideo(forms.ModelForm):
class Meta: class Meta:
model = UploadVideo model = UploadVideo
fields = ('title', 'video', 'course',) fields = (
"title",
"video",
"course",
)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['title'].widget.attrs.update({'class': 'form-control'}) self.fields["title"].widget.attrs.update({"class": "form-control"})
self.fields['video'].widget.attrs.update({'class': 'form-control'}) self.fields["video"].widget.attrs.update({"class": "form-control"})

View File

@ -10,13 +10,13 @@ from .utils import *
YEARS = ( YEARS = (
(1, '1'), (1, "1"),
(2, '2'), (2, "2"),
(3, '3'), (3, "3"),
(4, '4'), (4, "4"),
(4, '5'), (4, "5"),
(4, '6'), (4, "6"),
) )
# LEVEL_COURSE = "Level course" # LEVEL_COURSE = "Level course"
BACHLOAR_DEGREE = "Bachloar" BACHLOAR_DEGREE = "Bachloar"
@ -43,10 +43,10 @@ class ProgramManager(models.Manager):
def search(self, query=None): def search(self, query=None):
qs = self.get_queryset() qs = self.get_queryset()
if query is not None: if query is not None:
or_lookup = (Q(title__icontains=query) | or_lookup = Q(title__icontains=query) | Q(summary__icontains=query)
Q(summary__icontains=query) qs = qs.filter(
) or_lookup
qs = qs.filter(or_lookup).distinct() # distinct() is often necessary with Q lookups ).distinct() # distinct() is often necessary with Q lookups
return qs return qs
@ -60,19 +60,22 @@ class Program(models.Model):
return self.title return self.title
def get_absolute_url(self): def get_absolute_url(self):
return reverse('program_detail', kwargs={'pk': self.pk}) return reverse("program_detail", kwargs={"pk": self.pk})
class CourseManager(models.Manager): class CourseManager(models.Manager):
def search(self, query=None): def search(self, query=None):
qs = self.get_queryset() qs = self.get_queryset()
if query is not None: if query is not None:
or_lookup = (Q(title__icontains=query) | or_lookup = (
Q(summary__icontains=query)| Q(title__icontains=query)
Q(code__icontains=query)| | Q(summary__icontains=query)
Q(slug__icontains=query) | Q(code__icontains=query)
) | Q(slug__icontains=query)
qs = qs.filter(or_lookup).distinct() # distinct() is often necessary with Q lookups )
qs = qs.filter(
or_lookup
).distinct() # distinct() is often necessary with Q lookups
return qs return qs
@ -94,11 +97,12 @@ class Course(models.Model):
return "{0} ({1})".format(self.title, self.code) return "{0} ({1})".format(self.title, self.code)
def get_absolute_url(self): def get_absolute_url(self):
return reverse('course_detail', kwargs={'slug': self.slug}) return reverse("course_detail", kwargs={"slug": self.slug})
@property @property
def is_current_semester(self): def is_current_semester(self):
from app.models import Semester from app.models import Semester
current_semester = Semester.objects.get(is_current_semester=True) current_semester = Semester.objects.get(is_current_semester=True)
if self.semester == current_semester.semester: if self.semester == current_semester.semester:
@ -111,25 +115,50 @@ def course_pre_save_receiver(sender, instance, *args, **kwargs):
if not instance.slug: if not instance.slug:
instance.slug = unique_slug_generator(instance) instance.slug = unique_slug_generator(instance)
pre_save.connect(course_pre_save_receiver, sender=Course) pre_save.connect(course_pre_save_receiver, sender=Course)
class CourseAllocation(models.Model): class CourseAllocation(models.Model):
lecturer = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='allocated_lecturer') lecturer = models.ForeignKey(
courses = models.ManyToManyField(Course, related_name='allocated_course') settings.AUTH_USER_MODEL,
session = models.ForeignKey("app.Session", on_delete=models.CASCADE, blank=True, null=True) on_delete=models.CASCADE,
related_name="allocated_lecturer",
)
courses = models.ManyToManyField(Course, related_name="allocated_course")
session = models.ForeignKey(
"app.Session", on_delete=models.CASCADE, blank=True, null=True
)
def __str__(self): def __str__(self):
return self.lecturer.get_full_name return self.lecturer.get_full_name
def get_absolute_url(self): def get_absolute_url(self):
return reverse('edit_allocated_course', kwargs={'pk': self.pk}) return reverse("edit_allocated_course", kwargs={"pk": self.pk})
class Upload(models.Model): class Upload(models.Model):
title = models.CharField(max_length=100) title = models.CharField(max_length=100)
course = models.ForeignKey(Course, on_delete=models.CASCADE) course = models.ForeignKey(Course, on_delete=models.CASCADE)
file = models.FileField(upload_to='course_files/', validators=[FileExtensionValidator(['pdf', 'docx', 'doc', 'xls', 'xlsx', 'ppt', 'pptx', 'zip', 'rar', '7zip'])]) file = models.FileField(
upload_to="course_files/",
validators=[
FileExtensionValidator(
[
"pdf",
"docx",
"doc",
"xls",
"xlsx",
"ppt",
"pptx",
"zip",
"rar",
"7zip",
]
)
],
)
updated_date = models.DateTimeField(auto_now=True, auto_now_add=False, null=True) updated_date = models.DateTimeField(auto_now=True, auto_now_add=False, null=True)
upload_time = models.DateTimeField(auto_now=False, auto_now_add=True, null=True) upload_time = models.DateTimeField(auto_now=False, auto_now_add=True, null=True)
@ -138,18 +167,18 @@ class Upload(models.Model):
def get_extension_short(self): def get_extension_short(self):
ext = str(self.file).split(".") ext = str(self.file).split(".")
ext = ext[len(ext)-1] ext = ext[len(ext) - 1]
if ext == 'doc' or ext == 'docx': if ext == "doc" or ext == "docx":
return 'word' return "word"
elif ext == 'pdf': elif ext == "pdf":
return 'pdf' return "pdf"
elif ext == 'xls' or ext == 'xlsx': elif ext == "xls" or ext == "xlsx":
return 'excel' return "excel"
elif ext == 'ppt' or ext == 'pptx': elif ext == "ppt" or ext == "pptx":
return 'powerpoint' return "powerpoint"
elif ext == 'zip' or ext == 'rar' or ext == '7zip': elif ext == "zip" or ext == "rar" or ext == "7zip":
return 'archive' return "archive"
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
self.file.delete() self.file.delete()
@ -160,7 +189,12 @@ class UploadVideo(models.Model):
title = models.CharField(max_length=100) title = models.CharField(max_length=100)
slug = models.SlugField(blank=True, unique=True) slug = models.SlugField(blank=True, unique=True)
course = models.ForeignKey(Course, on_delete=models.CASCADE) course = models.ForeignKey(Course, on_delete=models.CASCADE)
video = models.FileField(upload_to='course_videos/', validators=[FileExtensionValidator(['mp4', 'mkv', 'wmv', '3gp', 'f4v', 'avi', 'mp3'])]) video = models.FileField(
upload_to="course_videos/",
validators=[
FileExtensionValidator(["mp4", "mkv", "wmv", "3gp", "f4v", "avi", "mp3"])
],
)
summary = models.TextField(null=True, blank=True) summary = models.TextField(null=True, blank=True)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True, null=True) timestamp = models.DateTimeField(auto_now=False, auto_now_add=True, null=True)
@ -168,7 +202,9 @@ class UploadVideo(models.Model):
return str(self.title) return str(self.title)
def get_absolute_url(self): def get_absolute_url(self):
return reverse('video_single', kwargs={'slug': self.course.slug, 'video_slug': self.slug}) return reverse(
"video_single", kwargs={"slug": self.course.slug, "video_slug": self.slug}
)
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
self.video.delete() self.video.delete()
@ -179,12 +215,14 @@ def video_pre_save_receiver(sender, instance, *args, **kwargs):
if not instance.slug: if not instance.slug:
instance.slug = unique_slug_generator(instance) instance.slug = unique_slug_generator(instance)
pre_save.connect(video_pre_save_receiver, sender=UploadVideo) pre_save.connect(video_pre_save_receiver, sender=UploadVideo)
class CourseOffer(models.Model): class CourseOffer(models.Model):
"""NOTE: Only department head can offer semester courses""" """NOTE: Only department head can offer semester courses"""
dep_head = models.ForeignKey("accounts.DepartmentHead", on_delete=models.CASCADE)
def __str__(self): dep_head = models.ForeignKey("accounts.DepartmentHead", on_delete=models.CASCADE)
return "{}".format(self.dep_head)
def __str__(self):
return "{}".format(self.dep_head)

View File

@ -4,38 +4,66 @@ from .views import *
urlpatterns = [ urlpatterns = [
# Program urls # Program urls
path('', program_view, name='programs'), path("", program_view, name="programs"),
path('<int:pk>/detail/', program_detail, name='program_detail'), path("<int:pk>/detail/", program_detail, name="program_detail"),
path('add/', program_add, name='add_program'), path("add/", program_add, name="add_program"),
path('<int:pk>/edit/', program_edit, name='edit_program'), path("<int:pk>/edit/", program_edit, name="edit_program"),
path('<int:pk>/delete/', program_delete, name='program_delete'), path("<int:pk>/delete/", program_delete, name="program_delete"),
# Course urls # Course urls
path('course/<slug>/detail/', course_single, name='course_detail'), path("course/<slug>/detail/", course_single, name="course_detail"),
path('<int:pk>/course/add/', course_add, name='course_add'), path("<int:pk>/course/add/", course_add, name="course_add"),
path('course/<slug>/edit/', course_edit, name='edit_course'), path("course/<slug>/edit/", course_edit, name="edit_course"),
path('course/delete/<slug>/', course_delete, name='delete_course'), path("course/delete/<slug>/", course_delete, name="delete_course"),
# CourseAllocation urls # CourseAllocation urls
path('course/assign/', CourseAllocationFormView.as_view(), name='course_allocation'), path(
path('course/allocated/', course_allocation_view, name='course_allocation_view'), "course/assign/", CourseAllocationFormView.as_view(), name="course_allocation"
path('allocated_course/<int:pk>/edit/', edit_allocated_course, name='edit_allocated_course'), ),
path('course/<int:pk>/deallocate/', deallocate_course, name='course_deallocate'), path("course/allocated/", course_allocation_view, name="course_allocation_view"),
path(
"allocated_course/<int:pk>/edit/",
edit_allocated_course,
name="edit_allocated_course",
),
path("course/<int:pk>/deallocate/", deallocate_course, name="course_deallocate"),
# File uploads urls # File uploads urls
path('course/<slug>/documentations/upload/', handle_file_upload, name='upload_file_view'), path(
path('course/<slug>/documentations/<int:file_id>/edit/', handle_file_edit, name='upload_file_edit'), "course/<slug>/documentations/upload/",
path('course/<slug>/documentations/<int:file_id>/delete/', handle_file_delete, name='upload_file_delete'), handle_file_upload,
name="upload_file_view",
),
path(
"course/<slug>/documentations/<int:file_id>/edit/",
handle_file_edit,
name="upload_file_edit",
),
path(
"course/<slug>/documentations/<int:file_id>/delete/",
handle_file_delete,
name="upload_file_delete",
),
# Video uploads urls # Video uploads urls
path('course/<slug>/video_tutorials/upload/', handle_video_upload, name='upload_video'), path(
path('course/<slug>/video_tutorials/<video_slug>/detail/', handle_video_single, name='video_single'), "course/<slug>/video_tutorials/upload/",
path('course/<slug>/video_tutorials/<video_slug>/edit/', handle_video_edit, name='upload_video_edit'), handle_video_upload,
path('course/<slug>/video_tutorials/<video_slug>/delete/', handle_video_delete, name='upload_video_delete'), name="upload_video",
),
path(
"course/<slug>/video_tutorials/<video_slug>/detail/",
handle_video_single,
name="video_single",
),
path(
"course/<slug>/video_tutorials/<video_slug>/edit/",
handle_video_edit,
name="upload_video_edit",
),
path(
"course/<slug>/video_tutorials/<video_slug>/delete/",
handle_video_delete,
name="upload_video_delete",
),
# course registration # course registration
path('course/registration/', course_registration, name='course_registration'), path("course/registration/", course_registration, name="course_registration"),
path('course/drop/', course_drop, name='course_drop'), path("course/drop/", course_drop, name="course_drop"),
path("my_courses/", user_course_list, name="user_course_list"),
path('my_courses/', user_course_list, name="user_course_list"),
] ]

View File

@ -1,4 +1,4 @@
import datetime import datetime
import os import os
import random import random
import string import string
@ -7,12 +7,12 @@ from django.utils.text import slugify
def random_string_generator(size=10, chars=string.ascii_lowercase + string.digits): def random_string_generator(size=10, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size)) return "".join(random.choice(chars) for _ in range(size))
def unique_slug_generator(instance, new_slug=None): def unique_slug_generator(instance, new_slug=None):
""" """
This is for a Django project and it assumes your instance This is for a Django project and it assumes your instance
has a model with a slug field and a title character (char) field. has a model with a slug field and a title character (char) field.
""" """
if new_slug is not None: if new_slug is not None:
@ -24,8 +24,7 @@ def unique_slug_generator(instance, new_slug=None):
qs_exists = Klass.objects.filter(slug=slug).exists() qs_exists = Klass.objects.filter(slug=slug).exists()
if qs_exists: if qs_exists:
new_slug = "{slug}-{randstr}".format( new_slug = "{slug}-{randstr}".format(
slug=slug, slug=slug, randstr=random_string_generator(size=4)
randstr=random_string_generator(size=4) )
)
return unique_slug_generator(instance, new_slug=new_slug) return unique_slug_generator(instance, new_slug=new_slug)
return slug return slug

View File

@ -13,8 +13,12 @@ from app.models import Session, Semester
from result.models import TakenCourse from result.models import TakenCourse
from accounts.decorators import lecturer_required, student_required from accounts.decorators import lecturer_required, student_required
from .forms import ( from .forms import (
ProgramForm, CourseAddForm, CourseAllocationForm, ProgramForm,
EditCourseAllocationForm, UploadFormFile, UploadFormVideo CourseAddForm,
CourseAllocationForm,
EditCourseAllocationForm,
UploadFormFile,
UploadFormVideo,
) )
from .models import Program, Course, CourseAllocation, Upload, UploadVideo from .models import Program, Course, CourseAllocation, Upload, UploadVideo
@ -26,51 +30,67 @@ from .models import Program, Course, CourseAllocation, Upload, UploadVideo
def program_view(request): def program_view(request):
programs = Program.objects.all() programs = Program.objects.all()
program_filter = request.GET.get('program_filter') program_filter = request.GET.get("program_filter")
if program_filter: if program_filter:
programs = Program.objects.filter(title__icontains=program_filter) programs = Program.objects.filter(title__icontains=program_filter)
return render(request, 'course/program_list.html', { return render(
'title': "Programs | DjangoSMS", request,
'programs': programs, "course/program_list.html",
}) {
"title": "Programs | DjangoSMS",
"programs": programs,
},
)
@login_required @login_required
@lecturer_required @lecturer_required
def program_add(request): def program_add(request):
if request.method == 'POST': if request.method == "POST":
form = ProgramForm(request.POST) form = ProgramForm(request.POST)
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, request.POST.get('title') + ' program has been created.') messages.success(
return redirect('programs') request, request.POST.get("title") + " program has been created."
)
return redirect("programs")
else: else:
messages.error(request, 'Correct the error(S) below.') messages.error(request, "Correct the error(S) below.")
else: else:
form = ProgramForm() form = ProgramForm()
return render(request, 'course/program_add.html', { return render(
'title': "Add Program | DjangoSMS", request,
'form': form, "course/program_add.html",
}) {
"title": "Add Program | DjangoSMS",
"form": form,
},
)
@login_required @login_required
def program_detail(request, pk): def program_detail(request, pk):
program = Program.objects.get(pk=pk) program = Program.objects.get(pk=pk)
courses = Course.objects.filter(program_id=pk).order_by('-year') courses = Course.objects.filter(program_id=pk).order_by("-year")
credits = Course.objects.aggregate(Sum('credit')) credits = Course.objects.aggregate(Sum("credit"))
paginator = Paginator(courses, 10) paginator = Paginator(courses, 10)
page = request.GET.get('page') page = request.GET.get("page")
courses = paginator.get_page(page) courses = paginator.get_page(page)
return render(request, 'course/program_single.html', { return render(
'title': program.title, request,
'program': program, 'courses': courses, 'credits': credits "course/program_single.html",
}, ) {
"title": program.title,
"program": program,
"courses": courses,
"credits": credits,
},
)
@login_required @login_required
@ -78,19 +98,22 @@ def program_detail(request, pk):
def program_edit(request, pk): def program_edit(request, pk):
program = Program.objects.get(pk=pk) program = Program.objects.get(pk=pk)
if request.method == 'POST': if request.method == "POST":
form = ProgramForm(request.POST, instance=program) form = ProgramForm(request.POST, instance=program)
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, str(request.POST.get('title')) + ' program has been updated.') messages.success(
return redirect('programs') request, str(request.POST.get("title")) + " program has been updated."
)
return redirect("programs")
else: else:
form = ProgramForm(instance=program) form = ProgramForm(instance=program)
return render(request, 'course/program_add.html', { return render(
'title': "Edit Program | DjangoSMS", request,
'form': form "course/program_add.html",
}) {"title": "Edit Program | DjangoSMS", "form": form},
)
@login_required @login_required
@ -99,11 +122,14 @@ def program_delete(request, pk):
program = Program.objects.get(pk=pk) program = Program.objects.get(pk=pk)
title = program.title title = program.title
program.delete() program.delete()
messages.success(request, 'Program ' + title + ' has been deleted.') messages.success(request, "Program " + title + " has been deleted.")
return redirect("programs")
return redirect('programs')
# ######################################################## # ########################################################
# ######################################################## # ########################################################
# Course views # Course views
# ######################################################## # ########################################################
@ -116,61 +142,79 @@ def course_single(request, slug):
# lecturers = User.objects.filter(allocated_lecturer__pk=course.id) # lecturers = User.objects.filter(allocated_lecturer__pk=course.id)
lecturers = CourseAllocation.objects.filter(courses__pk=course.id) lecturers = CourseAllocation.objects.filter(courses__pk=course.id)
return render(request, 'course/course_single.html', { return render(
'title': course.title, request,
'course': course, "course/course_single.html",
'files': files, {
'videos': videos, "title": course.title,
'lecturers': lecturers, "course": course,
'media_url': settings.MEDIA_ROOT, "files": files,
}, ) "videos": videos,
"lecturers": lecturers,
"media_url": settings.MEDIA_ROOT,
},
)
@login_required @login_required
@lecturer_required @lecturer_required
def course_add(request, pk): def course_add(request, pk):
users = User.objects.all() users = User.objects.all()
if request.method == 'POST': if request.method == "POST":
form = CourseAddForm(request.POST) form = CourseAddForm(request.POST)
course_name = request.POST.get('title') course_name = request.POST.get("title")
course_code = request.POST.get('code') course_code = request.POST.get("code")
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, (course_name + '(' + course_code + ')' + ' has been created.')) messages.success(
return redirect('program_detail', pk=request.POST.get('program')) request, (course_name + "(" + course_code + ")" + " has been created.")
)
return redirect("program_detail", pk=request.POST.get("program"))
else: else:
messages.error(request, 'Correct the error(s) below.') messages.error(request, "Correct the error(s) below.")
else: else:
form = CourseAddForm(initial={'program': Program.objects.get(pk=pk)}) form = CourseAddForm(initial={"program": Program.objects.get(pk=pk)})
return render(request, 'course/course_add.html', { return render(
'title': "Add Course | DjangoSMS", request,
'form': form, 'program': pk, 'users': users "course/course_add.html",
}, ) {
"title": "Add Course | DjangoSMS",
"form": form,
"program": pk,
"users": users,
},
)
@login_required @login_required
@lecturer_required @lecturer_required
def course_edit(request, slug): def course_edit(request, slug):
course = get_object_or_404(Course, slug=slug) course = get_object_or_404(Course, slug=slug)
if request.method == 'POST': if request.method == "POST":
form = CourseAddForm(request.POST, instance=course) form = CourseAddForm(request.POST, instance=course)
course_name = request.POST.get('title') course_name = request.POST.get("title")
course_code = request.POST.get('code') course_code = request.POST.get("code")
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, (course_name + '(' + course_code + ')' + ' has been updated.')) messages.success(
return redirect('program_detail', pk=request.POST.get('program')) request, (course_name + "(" + course_code + ")" + " has been updated.")
)
return redirect("program_detail", pk=request.POST.get("program"))
else: else:
messages.error(request, 'Correct the error(s) below.') messages.error(request, "Correct the error(s) below.")
else: else:
form = CourseAddForm(instance=course) form = CourseAddForm(instance=course)
return render(request, 'course/course_add.html', { return render(
'title': "Edit Course | DjangoSMS", request,
# 'form': form, 'program': pk, 'course': pk "course/course_add.html",
'form': form {
}, ) "title": "Edit Course | DjangoSMS",
# 'form': form, 'program': pk, 'course': pk
"form": form,
},
)
@login_required @login_required
@ -179,29 +223,31 @@ def course_delete(request, slug):
course = Course.objects.get(slug=slug) course = Course.objects.get(slug=slug)
# course_name = course.title # course_name = course.title
course.delete() course.delete()
messages.success(request, 'Course ' + course.title + ' has been deleted.') messages.success(request, "Course " + course.title + " has been deleted.")
return redirect("program_detail", pk=course.program.id)
return redirect('program_detail', pk=course.program.id)
# ######################################################## # ########################################################
# ######################################################## # ########################################################
# Course Allocation # Course Allocation
# ######################################################## # ########################################################
@method_decorator([login_required], name='dispatch') @method_decorator([login_required], name="dispatch")
class CourseAllocationFormView(CreateView): class CourseAllocationFormView(CreateView):
form_class = CourseAllocationForm form_class = CourseAllocationForm
template_name = 'course/course_allocation_form.html' template_name = "course/course_allocation_form.html"
def get_form_kwargs(self): def get_form_kwargs(self):
kwargs = super(CourseAllocationFormView, self).get_form_kwargs() kwargs = super(CourseAllocationFormView, self).get_form_kwargs()
kwargs['user'] = self.request.user kwargs["user"] = self.request.user
return kwargs return kwargs
def form_valid(self, form): def form_valid(self, form):
# if a staff has been allocated a course before update it else create new # if a staff has been allocated a course before update it else create new
lecturer = form.cleaned_data['lecturer'] lecturer = form.cleaned_data["lecturer"]
selected_courses = form.cleaned_data['courses'] selected_courses = form.cleaned_data["courses"]
courses = () courses = ()
for course in selected_courses: for course in selected_courses:
courses += (course.pk,) courses += (course.pk,)
@ -214,40 +260,45 @@ class CourseAllocationFormView(CreateView):
for i in range(0, selected_courses.count()): for i in range(0, selected_courses.count()):
a.courses.add(courses[i]) a.courses.add(courses[i])
a.save() a.save()
return redirect('course_allocation_view') return redirect("course_allocation_view")
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context['title'] = "Assign Course | DjangoSMS" context["title"] = "Assign Course | DjangoSMS"
return context return context
@login_required @login_required
def course_allocation_view(request): def course_allocation_view(request):
allocated_courses = CourseAllocation.objects.all() allocated_courses = CourseAllocation.objects.all()
return render(request, 'course/course_allocation_view.html', { return render(
'title': "Course Allocations | DjangoSMS", request,
"allocated_courses": allocated_courses "course/course_allocation_view.html",
}) {
"title": "Course Allocations | DjangoSMS",
"allocated_courses": allocated_courses,
},
)
@login_required @login_required
@lecturer_required @lecturer_required
def edit_allocated_course(request, pk): def edit_allocated_course(request, pk):
allocated = get_object_or_404(CourseAllocation, pk=pk) allocated = get_object_or_404(CourseAllocation, pk=pk)
if request.method == 'POST': if request.method == "POST":
form = EditCourseAllocationForm(request.POST, instance=allocated) form = EditCourseAllocationForm(request.POST, instance=allocated)
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, 'course assigned has been updated.') messages.success(request, "course assigned has been updated.")
return redirect('course_allocation_view') return redirect("course_allocation_view")
else: else:
form = EditCourseAllocationForm(instance=allocated) form = EditCourseAllocationForm(instance=allocated)
return render(request, 'course/course_allocation_form.html', { return render(
'title': "Edit Course Allocated | DjangoSMS", request,
'form': form, 'allocated': pk "course/course_allocation_form.html",
}, ) {"title": "Edit Course Allocated | DjangoSMS", "form": form, "allocated": pk},
)
@login_required @login_required
@ -255,8 +306,10 @@ def edit_allocated_course(request, pk):
def deallocate_course(request, pk): def deallocate_course(request, pk):
course = CourseAllocation.objects.get(pk=pk) course = CourseAllocation.objects.get(pk=pk)
course.delete() course.delete()
messages.success(request, 'successfully deallocate!') messages.success(request, "successfully deallocate!")
return redirect("course_allocation_view") return redirect("course_allocation_view")
# ######################################################## # ########################################################
@ -267,19 +320,22 @@ def deallocate_course(request, pk):
@lecturer_required @lecturer_required
def handle_file_upload(request, slug): def handle_file_upload(request, slug):
course = Course.objects.get(slug=slug) course = Course.objects.get(slug=slug)
if request.method == 'POST': if request.method == "POST":
form = UploadFormFile(request.POST, request.FILES, {'course': course}) form = UploadFormFile(request.POST, request.FILES, {"course": course})
# file_name = request.POST.get('name') # file_name = request.POST.get('name')
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, (request.POST.get('title') + ' has been uploaded.')) messages.success(
return redirect('course_detail', slug=slug) request, (request.POST.get("title") + " has been uploaded.")
)
return redirect("course_detail", slug=slug)
else: else:
form = UploadFormFile() form = UploadFormFile()
return render(request, 'upload/upload_file_form.html', { return render(
'title': "File Upload | DjangoSMS", request,
'form': form, 'course': course "upload/upload_file_form.html",
}) {"title": "File Upload | DjangoSMS", "form": form, "course": course},
)
@login_required @login_required
@ -287,19 +343,23 @@ def handle_file_upload(request, slug):
def handle_file_edit(request, slug, file_id): def handle_file_edit(request, slug, file_id):
course = Course.objects.get(slug=slug) course = Course.objects.get(slug=slug)
instance = Upload.objects.get(pk=file_id) instance = Upload.objects.get(pk=file_id)
if request.method == 'POST': if request.method == "POST":
form = UploadFormFile(request.POST, request.FILES, instance=instance) form = UploadFormFile(request.POST, request.FILES, instance=instance)
# file_name = request.POST.get('name') # file_name = request.POST.get('name')
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, (request.POST.get('title') + ' has been updated.')) messages.success(
return redirect('course_detail', slug=slug) request, (request.POST.get("title") + " has been updated.")
)
return redirect("course_detail", slug=slug)
else: else:
form = UploadFormFile(instance=instance) form = UploadFormFile(instance=instance)
return render(request, 'upload/upload_file_form.html', { return render(
'title': instance.title, request,
'form': form, 'course': course}) "upload/upload_file_form.html",
{"title": instance.title, "form": form, "course": course},
)
def handle_file_delete(request, slug, file_id): def handle_file_delete(request, slug, file_id):
@ -307,8 +367,9 @@ def handle_file_delete(request, slug, file_id):
# file_name = file.name # file_name = file.name
file.delete() file.delete()
messages.success(request, (file.title + ' has been deleted.')) messages.success(request, (file.title + " has been deleted."))
return redirect('course_detail', slug=slug) return redirect("course_detail", slug=slug)
# ######################################################## # ########################################################
# Video Upload views # Video Upload views
@ -317,18 +378,21 @@ def handle_file_delete(request, slug, file_id):
@lecturer_required @lecturer_required
def handle_video_upload(request, slug): def handle_video_upload(request, slug):
course = Course.objects.get(slug=slug) course = Course.objects.get(slug=slug)
if request.method == 'POST': if request.method == "POST":
form = UploadFormVideo(request.POST, request.FILES, {'course': course}) form = UploadFormVideo(request.POST, request.FILES, {"course": course})
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, (request.POST.get('title') + ' has been uploaded.')) messages.success(
return redirect('course_detail', slug=slug) request, (request.POST.get("title") + " has been uploaded.")
)
return redirect("course_detail", slug=slug)
else: else:
form = UploadFormVideo() form = UploadFormVideo()
return render(request, 'upload/upload_video_form.html', { return render(
'title': "Video Upload | DjangoSMS", request,
'form': form, 'course': course "upload/upload_video_form.html",
}) {"title": "Video Upload | DjangoSMS", "form": form, "course": course},
)
@login_required @login_required
@ -336,7 +400,7 @@ def handle_video_upload(request, slug):
def handle_video_single(request, slug, video_slug): def handle_video_single(request, slug, video_slug):
course = get_object_or_404(Course, slug=slug) course = get_object_or_404(Course, slug=slug)
video = get_object_or_404(UploadVideo, slug=video_slug) video = get_object_or_404(UploadVideo, slug=video_slug)
return render(request, 'upload/video_single.html', {'video': video}) return render(request, "upload/video_single.html", {"video": video})
@login_required @login_required
@ -344,18 +408,22 @@ def handle_video_single(request, slug, video_slug):
def handle_video_edit(request, slug, video_slug): def handle_video_edit(request, slug, video_slug):
course = Course.objects.get(slug=slug) course = Course.objects.get(slug=slug)
instance = UploadVideo.objects.get(slug=video_slug) instance = UploadVideo.objects.get(slug=video_slug)
if request.method == 'POST': if request.method == "POST":
form = UploadFormVideo(request.POST, request.FILES, instance=instance) form = UploadFormVideo(request.POST, request.FILES, instance=instance)
if form.is_valid(): if form.is_valid():
form.save() form.save()
messages.success(request, (request.POST.get('title') + ' has been updated.')) messages.success(
return redirect('course_detail', slug=slug) request, (request.POST.get("title") + " has been updated.")
)
return redirect("course_detail", slug=slug)
else: else:
form = UploadFormVideo(instance=instance) form = UploadFormVideo(instance=instance)
return render(request, 'upload/upload_video_form.html', { return render(
'title': instance.title, request,
'form': form, 'course': course}) "upload/upload_video_form.html",
{"title": instance.title, "form": form, "course": course},
)
def handle_video_delete(request, slug, video_slug): def handle_video_delete(request, slug, video_slug):
@ -363,8 +431,10 @@ def handle_video_delete(request, slug, video_slug):
# video = UploadVideo.objects.get(slug=video_slug) # video = UploadVideo.objects.get(slug=video_slug)
video.delete() video.delete()
messages.success(request, (video.title + ' has been deleted.')) messages.success(request, (video.title + " has been deleted."))
return redirect('course_detail', slug=slug) return redirect("course_detail", slug=slug)
# ######################################################## # ########################################################
@ -374,10 +444,10 @@ def handle_video_delete(request, slug, video_slug):
@login_required @login_required
@student_required @student_required
def course_registration(request): def course_registration(request):
if request.method == 'POST': if request.method == "POST":
ids = () ids = ()
data = request.POST.copy() data = request.POST.copy()
data.pop('csrfmiddlewaretoken', None) # remove csrf_token data.pop("csrfmiddlewaretoken", None) # remove csrf_token
for key in data.keys(): for key in data.keys():
ids = ids + (str(key),) ids = ids + (str(key),)
for s in range(0, len(ids)): for s in range(0, len(ids)):
@ -385,8 +455,8 @@ def course_registration(request):
course = Course.objects.get(pk=ids[s]) course = Course.objects.get(pk=ids[s])
obj = TakenCourse.objects.create(student=student, course=course) obj = TakenCourse.objects.create(student=student, course=course)
obj.save() obj.save()
messages.success(request, 'Courses Registered Successfully!') messages.success(request, "Courses Registered Successfully!")
return redirect('course_registration') return redirect("course_registration")
else: else:
# student = Student.objects.get(student__pk=request.user.id) # student = Student.objects.get(student__pk=request.user.id)
student = get_object_or_404(Student, student__id=request.user.id) student = get_object_or_404(Student, student__id=request.user.id)
@ -396,15 +466,26 @@ def course_registration(request):
t += (i.course.pk,) t += (i.course.pk,)
current_semester = Semester.objects.get(is_current_semester=True) current_semester = Semester.objects.get(is_current_semester=True)
courses = Course.objects.filter(program__pk=student.department.id, level=student.level, semester=current_semester courses = (
).exclude(id__in=t).order_by('year') Course.objects.filter(
all_courses = Course.objects.filter(level=student.level, program__pk=student.department.id) program__pk=student.department.id,
level=student.level,
semester=current_semester,
)
.exclude(id__in=t)
.order_by("year")
)
all_courses = Course.objects.filter(
level=student.level, program__pk=student.department.id
)
no_course_is_registered = False # Check if no course is registered no_course_is_registered = False # Check if no course is registered
all_courses_are_registered = False all_courses_are_registered = False
registered_courses = Course.objects.filter(level=student.level).filter(id__in=t) registered_courses = Course.objects.filter(level=student.level).filter(id__in=t)
if registered_courses.count() == 0: # Check if number of registered courses is 0 if (
registered_courses.count() == 0
): # Check if number of registered courses is 0
no_course_is_registered = True no_course_is_registered = True
if registered_courses.count() == all_courses.count(): if registered_courses.count() == all_courses.count():
@ -432,16 +513,16 @@ def course_registration(request):
"total_registered_credit": total_registered_credit, "total_registered_credit": total_registered_credit,
"student": student, "student": student,
} }
return render(request, 'course/course_registration.html', context) return render(request, "course/course_registration.html", context)
@login_required @login_required
@student_required @student_required
def course_drop(request): def course_drop(request):
if request.method == 'POST': if request.method == "POST":
ids = () ids = ()
data = request.POST.copy() data = request.POST.copy()
data.pop('csrfmiddlewaretoken', None) # remove csrf_token data.pop("csrfmiddlewaretoken", None) # remove csrf_token
for key in data.keys(): for key in data.keys():
ids = ids + (str(key),) ids = ids + (str(key),)
for s in range(0, len(ids)): for s in range(0, len(ids)):
@ -449,8 +530,10 @@ def course_drop(request):
course = Course.objects.get(pk=ids[s]) course = Course.objects.get(pk=ids[s])
obj = TakenCourse.objects.get(student=student, course=course) obj = TakenCourse.objects.get(student=student, course=course)
obj.delete() obj.delete()
messages.success(request, 'Successfully Dropped!') messages.success(request, "Successfully Dropped!")
return redirect('course_registration') return redirect("course_registration")
# ######################################################## # ########################################################
@ -459,18 +542,22 @@ def user_course_list(request):
if request.user.is_lecturer: if request.user.is_lecturer:
courses = Course.objects.filter(allocated_course__lecturer__pk=request.user.id) courses = Course.objects.filter(allocated_course__lecturer__pk=request.user.id)
return render(request, 'course/user_course_list.html', {'courses': courses}) return render(request, "course/user_course_list.html", {"courses": courses})
elif request.user.is_student: elif request.user.is_student:
student = Student.objects.get(student__pk=request.user.id) student = Student.objects.get(student__pk=request.user.id)
taken_courses = TakenCourse.objects.filter(student__student__id=student.student.id) taken_courses = TakenCourse.objects.filter(
courses = Course.objects.filter(level=student.level).filter(program__pk=student.department.id) student__student__id=student.student.id
)
courses = Course.objects.filter(level=student.level).filter(
program__pk=student.department.id
)
return render(request, 'course/user_course_list.html', { return render(
'student': student, request,
'taken_courses': taken_courses, "course/user_course_list.html",
'courses': courses {"student": student, "taken_courses": taken_courses, "courses": courses},
}) )
else: else:
return render(request, 'course/user_course_list.html') return render(request, "course/user_course_list.html")

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class PaymentsConfig(AppConfig): class PaymentsConfig(AppConfig):
name = 'payments' name = "payments"

View File

@ -3,8 +3,8 @@ from django.conf import settings
class Invoice(models.Model): class Invoice(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
total = models.FloatField(null=True, blank=True) total = models.FloatField(null=True, blank=True)
amount = models.FloatField(null=True, blank=True) amount = models.FloatField(null=True, blank=True)
payment_complete = models.BooleanField(default=False) payment_complete = models.BooleanField(default=False)
invoice_code = models.CharField(max_length=200, blank=True, null=True) invoice_code = models.CharField(max_length=200, blank=True, null=True)

View File

@ -2,18 +2,15 @@ from django.urls import path
from . import views from . import views
urlpatterns = [ urlpatterns = [
path('', views.PaymentGetwaysView.as_view(), name='payment_gateways'), path("", views.PaymentGetwaysView.as_view(), name="payment_gateways"),
path("paypal/", views.payment_paypal, name="paypal"),
path('paypal/', views.payment_paypal, name="paypal"), path("stripe/", views.payment_stripe, name="stripe"),
path('stripe/', views.payment_stripe, name="stripe"), path("coinbase/", views.payment_coinbase, name="coinbase"),
path('coinbase/', views.payment_coinbase, name="coinbase"), path("paylike/", views.payment_paylike, name="paylike"),
path('paylike/', views.payment_paylike, name="paylike"), path("stripe-charge/", views.stripe_charge, name="stripe_charge"),
path("gopay-charge/", views.gopay_charge, name="gopay_charge"),
path('stripe-charge/', views.stripe_charge, name='stripe_charge'), path("payment-succeed/", views.payment_succeed, name="payment-succeed"),
path('gopay-charge/', views.gopay_charge, name="gopay_charge"), path("complete/", views.paymentComplete, name="complete"),
path("create-invoice/", views.create_invoice, name="create_invoice"),
path('payment-succeed/', views.payment_succeed, name="payment-succeed"), path("invoice-detail/<int:id>/", views.invoice_detail, name="invoice_detail"),
path('complete/', views.paymentComplete, name="complete"),
path('create-invoice/', views.create_invoice, name="create_invoice"),
path('invoice-detail/<int:id>/', views.invoice_detail, name="invoice_detail"),
] ]

View File

@ -16,155 +16,157 @@ from .models import Invoice
def payment_paypal(request): def payment_paypal(request):
return render(request, 'payments/paypal.html', context={}) return render(request, "payments/paypal.html", context={})
def payment_stripe(request): def payment_stripe(request):
return render(request, 'payments/stripe.html', context={}) return render(request, "payments/stripe.html", context={})
def payment_coinbase(request): def payment_coinbase(request):
return render(request, 'payments/coinbase.html', context={}) return render(request, "payments/coinbase.html", context={})
def payment_paylike(request): def payment_paylike(request):
return render(request, 'payments/paylike.html', context={}) return render(request, "payments/paylike.html", context={})
def payment_succeed(request): def payment_succeed(request):
return render(request, 'payments/payment_succeed.html', context={}) return render(request, "payments/payment_succeed.html", context={})
class PaymentGetwaysView(TemplateView): class PaymentGetwaysView(TemplateView):
template_name = 'payments/payment_gateways.html' template_name = "payments/payment_gateways.html"
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(PaymentGetwaysView, self).get_context_data(**kwargs) context = super(PaymentGetwaysView, self).get_context_data(**kwargs)
context['key'] = settings.STRIPE_PUBLISHABLE_KEY context["key"] = settings.STRIPE_PUBLISHABLE_KEY
context['amount'] = 500 context["amount"] = 500
context['description'] = "Stripe Payment" context["description"] = "Stripe Payment"
context['invoice_session'] = self.request.session['invoice_session'] context["invoice_session"] = self.request.session["invoice_session"]
print(context['invoice_session']) print(context["invoice_session"])
return context return context
def stripe_charge(request): def stripe_charge(request):
stripe.api_key = settings.STRIPE_SECRET_KEY stripe.api_key = settings.STRIPE_SECRET_KEY
if request.method == 'POST': if request.method == "POST":
charge = stripe.Charge.create( charge = stripe.Charge.create(
amount=500, amount=500,
currency='eur', currency="eur",
description='A Django charge', description="A Django charge",
source=request.POST['stripeToken'] source=request.POST["stripeToken"],
) )
invoice_code = request.session['invoice_session'] invoice_code = request.session["invoice_session"]
invoice = Invoice.objects.get(invoice_code=invoice_code) invoice = Invoice.objects.get(invoice_code=invoice_code)
invoice.payment_complete = True invoice.payment_complete = True
invoice.save() invoice.save()
return redirect('completed') return redirect("completed")
# return JsonResponse({"invoice_code": invoice.invoice_code}, status=201) # return JsonResponse({"invoice_code": invoice.invoice_code}, status=201)
# return render(request, 'payments/charge.html') # return render(request, 'payments/charge.html')
def gopay_charge(request): def gopay_charge(request):
if request.method == 'POST': if request.method == "POST":
user = request.user user = request.user
payments = gopay.payments({ payments = gopay.payments(
'goid': '[PAYMENT_ID]', {
'clientId': '[GOPAY_CLIENT_ID]', "goid": "[PAYMENT_ID]",
'clientSecret': '[GOPAY_CLIENT_SECRET]', "clientId": "[GOPAY_CLIENT_ID]",
'isProductionMode': False, "clientSecret": "[GOPAY_CLIENT_SECRET]",
'scope': gopay.TokenScope.ALL, "isProductionMode": False,
'language': gopay.Language.ENGLISH, "scope": gopay.TokenScope.ALL,
'timeout': 30 "language": gopay.Language.ENGLISH,
}) "timeout": 30,
}
)
# recurrent payment must have field '' # recurrent payment must have field ''
recurrentPayment = { recurrentPayment = {
'recurrence': { "recurrence": {
'recurrence_cycle': Recurrence.DAILY, "recurrence_cycle": Recurrence.DAILY,
'recurrence_period': "7", "recurrence_period": "7",
'recurrence_date_to': '2015-12-31' "recurrence_date_to": "2015-12-31",
} }
} }
# pre-authorized payment must have field 'preauthorization' # pre-authorized payment must have field 'preauthorization'
preauthorizedPayment = { preauthorizedPayment = {"preauthorization": True}
'preauthorization': True
}
response = payments.create_payment({ response = payments.create_payment(
'payer': { {
'default_payment_instrument': PaymentInstrument.BANK_ACCOUNT, "payer": {
'allowed_payment_instruments': [PaymentInstrument.BANK_ACCOUNT], "default_payment_instrument": PaymentInstrument.BANK_ACCOUNT,
'default_swift': BankSwiftCode.FIO_BANKA, "allowed_payment_instruments": [PaymentInstrument.BANK_ACCOUNT],
'allowed_swifts': [BankSwiftCode.FIO_BANKA, BankSwiftCode.MBANK], "default_swift": BankSwiftCode.FIO_BANKA,
'contact': { "allowed_swifts": [BankSwiftCode.FIO_BANKA, BankSwiftCode.MBANK],
'first_name': user.first_name, "contact": {
'last_name': user.last_name, "first_name": user.first_name,
'email': user.email, "last_name": user.last_name,
'phone_number': user.phone, "email": user.email,
'city': 'example city', "phone_number": user.phone,
'street': 'Plana 67', "city": "example city",
'postal_code': '373 01', "street": "Plana 67",
'country_code': 'CZE', "postal_code": "373 01",
"country_code": "CZE",
},
}, },
}, "amount": 150,
'amount': 150, "currency": Currency.CZECH_CROWNS,
'currency': Currency.CZECH_CROWNS, "order_number": "001",
'order_number': '001', "order_description": "pojisteni01",
'order_description': 'pojisteni01', "items": [
'items': [ {"name": "item01", "amount": 50},
{'name': 'item01', 'amount': 50}, {"name": "item02", "amount": 100},
{'name': 'item02', 'amount': 100}, ],
], "additional_params": [{"name": "invoicenumber", "value": "2015001003"}],
'additional_params': [ "callback": {
{'name': 'invoicenumber', 'value': '2015001003'} "return_url": "http://www.your-url.tld/return",
], "notification_url": "http://www.your-url.tld/notify",
'callback': { },
'return_url': 'http://www.your-url.tld/return', "lang": Language.CZECH, # if lang is not specified, then default lang is used
'notification_url': 'http://www.your-url.tld/notify' }
}, )
'lang': Language.CZECH, # if lang is not specified, then default lang is used
})
if response.has_succeed(): if response.has_succeed():
print("\nPayment Succeed\n") print("\nPayment Succeed\n")
print("hooray, API returned " + str(response)) print("hooray, API returned " + str(response))
else: else:
print("\nPayment Fail\n") print("\nPayment Fail\n")
print("oops, API returned " + str(response.status_code) + ": " + str(response)) print(
"oops, API returned " + str(response.status_code) + ": " + str(response)
)
return JsonResponse({"message": str(response)}) return JsonResponse({"message": str(response)})
return JsonResponse({"message": "GET requested"}) return JsonResponse({"message": "GET requested"})
def paymentComplete(request): def paymentComplete(request):
print(request.is_ajax()) print(request.is_ajax())
if request.is_ajax() or request.method == 'POST': if request.is_ajax() or request.method == "POST":
invoice_id = request.session['invoice_session'] invoice_id = request.session["invoice_session"]
invoice = Invoice.objects.get(id=invoice_id) invoice = Invoice.objects.get(id=invoice_id)
invoice.payment_complete = True invoice.payment_complete = True
invoice.save() invoice.save()
# return redirect('invoice', invoice.invoice_code) # return redirect('invoice', invoice.invoice_code)
body = json.loads(request.body) body = json.loads(request.body)
print('BODY:', body) print("BODY:", body)
return JsonResponse('Payment completed!', safe=False) return JsonResponse("Payment completed!", safe=False)
def create_invoice(request): def create_invoice(request):
print(request.is_ajax()) print(request.is_ajax())
if request.method == 'POST': if request.method == "POST":
invoice = Invoice.objects.create( invoice = Invoice.objects.create(
user = request.user, user=request.user,
amount = request.POST.get('amount'), amount=request.POST.get("amount"),
total=26, total=26,
invoice_code=str(uuid.uuid4()), invoice_code=str(uuid.uuid4()),
) )
request.session['invoice_session'] = invoice.invoice_code request.session["invoice_session"] = invoice.invoice_code
return redirect('payment_gateways') return redirect("payment_gateways")
# if request.is_ajax(): # if request.is_ajax():
# invoice = Invoice.objects.create( # invoice = Invoice.objects.create(
# user = request.user, # user = request.user,
@ -173,12 +175,16 @@ def create_invoice(request):
# ) # )
# return JsonResponse({'invoice': invoice}, status=201) # created # return JsonResponse({'invoice': invoice}, status=201) # created
return render(request, 'invoices.html', context={ return render(
'invoices': Invoice.objects.filter(user=request.user) request,
}) "invoices.html",
context={"invoices": Invoice.objects.filter(user=request.user)},
)
def invoice_detail(request, slug): def invoice_detail(request, slug):
return render(request, 'invoice_detail.html', context={ return render(
'invoice': Invoice.objects.get(invoice_code=slug) request,
}) "invoice_detail.html",
context={"invoice": Invoice.objects.get(invoice_code=slug)},
)

View File

@ -3,7 +3,15 @@ from django.contrib import admin
from django.contrib.admin.widgets import FilteredSelectMultiple from django.contrib.admin.widgets import FilteredSelectMultiple
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from .models import Quiz, Progress, Question, MCQuestion, Choice, Essay_Question, Sitting from .models import (
Quiz,
Progress,
Question,
MCQuestion,
Choice,
Essay_Question,
Sitting,
)
class ChoiceInline(admin.TabularInline): class ChoiceInline(admin.TabularInline):
@ -11,7 +19,6 @@ class ChoiceInline(admin.TabularInline):
class QuizAdminForm(forms.ModelForm): class QuizAdminForm(forms.ModelForm):
class Meta: class Meta:
model = Quiz model = Quiz
exclude = [] exclude = []
@ -20,19 +27,20 @@ class QuizAdminForm(forms.ModelForm):
queryset=Question.objects.all().select_subclasses(), queryset=Question.objects.all().select_subclasses(),
required=False, required=False,
label=_("Questions"), label=_("Questions"),
widget=FilteredSelectMultiple( widget=FilteredSelectMultiple(verbose_name=_("Questions"), is_stacked=False),
verbose_name=_("Questions"), )
is_stacked=False))
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(QuizAdminForm, self).__init__(*args, **kwargs) super(QuizAdminForm, self).__init__(*args, **kwargs)
if self.instance.pk: if self.instance.pk:
self.fields['questions'].initial = self.instance.question_set.all().select_subclasses() self.fields[
"questions"
].initial = self.instance.question_set.all().select_subclasses()
def save(self, commit=True): def save(self, commit=True):
quiz = super(QuizAdminForm, self).save(commit=False) quiz = super(QuizAdminForm, self).save(commit=False)
quiz.save() quiz.save()
quiz.question_set.set(self.cleaned_data['questions']) quiz.question_set.set(self.cleaned_data["questions"])
self.save_m2m() self.save_m2m()
return quiz return quiz
@ -40,32 +48,43 @@ class QuizAdminForm(forms.ModelForm):
class QuizAdmin(admin.ModelAdmin): class QuizAdmin(admin.ModelAdmin):
form = QuizAdminForm form = QuizAdminForm
list_display = ('title', ) list_display = ("title",)
# list_filter = ('category',) # list_filter = ('category',)
search_fields = ('description', 'category', ) search_fields = (
"description",
"category",
)
class MCQuestionAdmin(admin.ModelAdmin): class MCQuestionAdmin(admin.ModelAdmin):
list_display = ('content', ) list_display = ("content",)
# list_filter = ('category',) # list_filter = ('category',)
fields = ('content', 'figure', 'quiz', 'explanation', 'choice_order') fields = ("content", "figure", "quiz", "explanation", "choice_order")
search_fields = ('content', 'explanation') search_fields = ("content", "explanation")
filter_horizontal = ('quiz',) filter_horizontal = ("quiz",)
inlines = [ChoiceInline] inlines = [ChoiceInline]
class ProgressAdmin(admin.ModelAdmin): class ProgressAdmin(admin.ModelAdmin):
search_fields = ('user', 'score', ) search_fields = (
"user",
"score",
)
class EssayQuestionAdmin(admin.ModelAdmin): class EssayQuestionAdmin(admin.ModelAdmin):
list_display = ('content', ) list_display = ("content",)
# list_filter = ('category',) # list_filter = ('category',)
fields = ('content', 'quiz', 'explanation', ) fields = (
search_fields = ('content', 'explanation') "content",
filter_horizontal = ('quiz',) "quiz",
"explanation",
)
search_fields = ("content", "explanation")
filter_horizontal = ("quiz",)
admin.site.register(Quiz, QuizAdmin) admin.site.register(Quiz, QuizAdmin)
admin.site.register(MCQuestion, MCQuestionAdmin) admin.site.register(MCQuestion, MCQuestionAdmin)

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class QuizConfig(AppConfig): class QuizConfig(AppConfig):
name = 'quiz' name = "quiz"

View File

@ -14,18 +14,20 @@ class QuestionForm(forms.Form):
def __init__(self, question, *args, **kwargs): def __init__(self, question, *args, **kwargs):
super(QuestionForm, self).__init__(*args, **kwargs) super(QuestionForm, self).__init__(*args, **kwargs)
choice_list = [x for x in question.get_choices_list()] choice_list = [x for x in question.get_choices_list()]
self.fields["answers"] = forms.ChoiceField(choices=choice_list, widget=RadioSelect) self.fields["answers"] = forms.ChoiceField(
choices=choice_list, widget=RadioSelect
)
class EssayForm(forms.Form): class EssayForm(forms.Form):
def __init__(self, question, *args, **kwargs): def __init__(self, question, *args, **kwargs):
super(EssayForm, self).__init__(*args, **kwargs) super(EssayForm, self).__init__(*args, **kwargs)
self.fields["answers"] = forms.CharField( self.fields["answers"] = forms.CharField(
widget=Textarea(attrs={'style': 'width:100%'})) widget=Textarea(attrs={"style": "width:100%"})
)
class QuizAddForm(forms.ModelForm): class QuizAddForm(forms.ModelForm):
class Meta: class Meta:
model = Quiz model = Quiz
exclude = [] exclude = []
@ -34,30 +36,35 @@ class QuizAddForm(forms.ModelForm):
queryset=Question.objects.all().select_subclasses(), queryset=Question.objects.all().select_subclasses(),
required=False, required=False,
label=_("Questions"), label=_("Questions"),
widget=FilteredSelectMultiple( widget=FilteredSelectMultiple(verbose_name=_("Questions"), is_stacked=False),
verbose_name=_("Questions"), )
is_stacked=False))
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(QuizAddForm, self).__init__(*args, **kwargs) super(QuizAddForm, self).__init__(*args, **kwargs)
if self.instance.pk: if self.instance.pk:
self.fields['questions'].initial = self.instance.question_set.all().select_subclasses() self.fields[
"questions"
].initial = self.instance.question_set.all().select_subclasses()
def save(self, commit=True): def save(self, commit=True):
quiz = super(QuizAddForm, self).save(commit=False) quiz = super(QuizAddForm, self).save(commit=False)
quiz.save() quiz.save()
quiz.question_set.set(self.cleaned_data['questions']) quiz.question_set.set(self.cleaned_data["questions"])
self.save_m2m() self.save_m2m()
return quiz return quiz
class MCQuestionForm(forms.ModelForm): class MCQuestionForm(forms.ModelForm):
class Meta: class Meta:
model = MCQuestion model = MCQuestion
exclude = () exclude = ()
MCQuestionFormSet = inlineformset_factory( MCQuestionFormSet = inlineformset_factory(
MCQuestion, Choice, form=MCQuestionForm, fields=['choice', 'correct'], can_delete=True, extra=5 MCQuestion,
Choice,
form=MCQuestionForm,
fields=["choice", "correct"],
can_delete=True,
extra=5,
) )

View File

@ -4,7 +4,10 @@ import json
from django.db import models from django.db import models
from django.urls import reverse from django.urls import reverse
from django.core.exceptions import ValidationError, ImproperlyConfigured from django.core.exceptions import ValidationError, ImproperlyConfigured
from django.core.validators import (MaxValueValidator, validate_comma_separated_integer_list,) from django.core.validators import (
MaxValueValidator,
validate_comma_separated_integer_list,
)
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.utils.timezone import now from django.utils.timezone import now
from django.conf import settings from django.conf import settings
@ -17,15 +20,15 @@ from course.models import Course
from .utils import * from .utils import *
CHOICE_ORDER_OPTIONS = ( CHOICE_ORDER_OPTIONS = (
('content', _('Content')), ("content", _("Content")),
('random', _('Random')), ("random", _("Random")),
('none', _('None')) ("none", _("None")),
) )
CATEGORY_OPTIONS = ( CATEGORY_OPTIONS = (
('assignment', _('Assignment')), ("assignment", _("Assignment")),
('exam', _('Exam')), ("exam", _("Exam")),
('practice', _('Practice Quiz')) ("practice", _("Practice Quiz")),
) )
@ -33,12 +36,15 @@ class QuizManager(models.Manager):
def search(self, query=None): def search(self, query=None):
qs = self.get_queryset() qs = self.get_queryset()
if query is not None: if query is not None:
or_lookup = (Q(title__icontains=query) | or_lookup = (
Q(description__icontains=query)| Q(title__icontains=query)
Q(category__icontains=query)| | Q(description__icontains=query)
Q(slug__icontains=query) | Q(category__icontains=query)
) | Q(slug__icontains=query)
qs = qs.filter(or_lookup).distinct() # distinct() is often necessary with Q lookups )
qs = qs.filter(
or_lookup
).distinct() # distinct() is often necessary with Q lookups
return qs return qs
@ -46,42 +52,76 @@ class Quiz(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE, null=True) course = models.ForeignKey(Course, on_delete=models.CASCADE, null=True)
title = models.CharField(verbose_name=_("Title"), max_length=60, blank=False) title = models.CharField(verbose_name=_("Title"), max_length=60, blank=False)
slug = models.SlugField(blank=True, unique=True) slug = models.SlugField(blank=True, unique=True)
description = models.TextField(verbose_name=_("Description"), blank=True, help_text=_("a description of the quiz")) description = models.TextField(
verbose_name=_("Description"),
blank=True,
help_text=_("a description of the quiz"),
)
category = models.TextField(choices=CATEGORY_OPTIONS, blank=True) category = models.TextField(choices=CATEGORY_OPTIONS, blank=True)
random_order = models.BooleanField(blank=False, default=False, verbose_name=_("Random Order"), random_order = models.BooleanField(
help_text=_("Display the questions in a random order or as they are set?")) blank=False,
default=False,
verbose_name=_("Random Order"),
help_text=_("Display the questions in a random order or as they are set?"),
)
# max_questions = models.PositiveIntegerField(blank=True, null=True, verbose_name=_("Max Questions"), # max_questions = models.PositiveIntegerField(blank=True, null=True, verbose_name=_("Max Questions"),
# help_text=_("Number of questions to be answered on each attempt.")) # help_text=_("Number of questions to be answered on each attempt."))
answers_at_end = models.BooleanField(blank=False, default=False, verbose_name=_("Answers at end"), answers_at_end = models.BooleanField(
help_text=_("Correct answer is NOT shown after question. Answers displayed at the end.")) blank=False,
default=False,
verbose_name=_("Answers at end"),
help_text=_(
"Correct answer is NOT shown after question. Answers displayed at the end."
),
)
exam_paper = models.BooleanField(blank=False, default=False, verbose_name=_("Exam Paper"), exam_paper = models.BooleanField(
help_text=_("If yes, the result of each attempt by a user will be stored. Necessary for marking.")) blank=False,
default=False,
verbose_name=_("Exam Paper"),
help_text=_(
"If yes, the result of each attempt by a user will be stored. Necessary for marking."
),
)
single_attempt = models.BooleanField(blank=False, default=False, verbose_name=_("Single Attempt"), single_attempt = models.BooleanField(
help_text=_("If yes, only one attempt by a user will be permitted.")) blank=False,
default=False,
verbose_name=_("Single Attempt"),
help_text=_("If yes, only one attempt by a user will be permitted."),
)
pass_mark = models.SmallIntegerField(blank=True, default=50, verbose_name=_("Pass Mark"), validators=[MaxValueValidator(100)], pass_mark = models.SmallIntegerField(
help_text=_("Percentage required to pass exam.")) blank=True,
default=50,
verbose_name=_("Pass Mark"),
validators=[MaxValueValidator(100)],
help_text=_("Percentage required to pass exam."),
)
draft = models.BooleanField(blank=True, default=False, verbose_name=_("Draft"), draft = models.BooleanField(
help_text=_("If yes, the quiz is not displayed in the quiz list and can only be taken by users who can edit quizzes.")) blank=True,
default=False,
verbose_name=_("Draft"),
help_text=_(
"If yes, the quiz is not displayed in the quiz list and can only be taken by users who can edit quizzes."
),
)
timestamp = models.DateTimeField(auto_now=True) timestamp = models.DateTimeField(auto_now=True)
objects = QuizManager() objects = QuizManager()
def save(self, force_insert=False, force_update=False, *args, **kwargs): def save(self, force_insert=False, force_update=False, *args, **kwargs):
if self.single_attempt is True: if self.single_attempt is True:
self.exam_paper = True self.exam_paper = True
if self.pass_mark > 100: if self.pass_mark > 100:
raise ValidationError('%s is above 100' % self.pass_mark) raise ValidationError("%s is above 100" % self.pass_mark)
if self.pass_mark < 0: if self.pass_mark < 0:
raise ValidationError('%s is below 0' % self.pass_mark) raise ValidationError("%s is below 0" % self.pass_mark)
super(Quiz, self).save(force_insert, force_update, *args, **kwargs) super(Quiz, self).save(force_insert, force_update, *args, **kwargs)
@ -101,18 +141,18 @@ class Quiz(models.Model):
def get_absolute_url(self): def get_absolute_url(self):
# return reverse('quiz_start_page', kwargs={'pk': self.pk}) # return reverse('quiz_start_page', kwargs={'pk': self.pk})
return reverse('quiz_index', kwargs={'slug': self.course.slug}) return reverse("quiz_index", kwargs={"slug": self.course.slug})
def quiz_pre_save_receiver(sender, instance, *args, **kwargs): def quiz_pre_save_receiver(sender, instance, *args, **kwargs):
if not instance.slug: if not instance.slug:
instance.slug = unique_slug_generator(instance) instance.slug = unique_slug_generator(instance)
pre_save.connect(quiz_pre_save_receiver, sender=Quiz) pre_save.connect(quiz_pre_save_receiver, sender=Quiz)
class ProgressManager(models.Manager): class ProgressManager(models.Manager):
def new_progress(self, user): def new_progress(self, user):
new_progress = self.create(user=user, score="") new_progress = self.create(user=user, score="")
new_progress.save() new_progress.save()
@ -120,8 +160,14 @@ class ProgressManager(models.Manager):
class Progress(models.Model): class Progress(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, verbose_name=_("User"), on_delete=models.CASCADE) user = models.OneToOneField(
score = models.CharField(max_length=1024, verbose_name=_("Score"), validators=[validate_comma_separated_integer_list]) settings.AUTH_USER_MODEL, verbose_name=_("User"), on_delete=models.CASCADE
)
score = models.CharField(
max_length=1024,
verbose_name=_("Score"),
validators=[validate_comma_separated_integer_list],
)
objects = ProgressManager() objects = ProgressManager()
@ -143,7 +189,17 @@ class Progress(models.Model):
def update_score(self, question, score_to_add=0, possible_to_add=0): def update_score(self, question, score_to_add=0, possible_to_add=0):
# category_test = Category.objects.filter(category=question.category).exists() # category_test = Category.objects.filter(category=question.category).exists()
if any([item is False for item in [score_to_add, possible_to_add, isinstance(score_to_add, int), isinstance(possible_to_add, int)]]): if any(
[
item is False
for item in [
score_to_add,
possible_to_add,
isinstance(score_to_add, int),
isinstance(possible_to_add, int),
]
]
):
return _("error"), _("category does not exist or invalid score") return _("error"), _("category does not exist or invalid score")
to_find = re.escape(str(question.quiz)) + r",(?P<score>\d+),(?P<possible>\d+)," to_find = re.escape(str(question.quiz)) + r",(?P<score>\d+),(?P<possible>\d+),"
@ -151,10 +207,12 @@ class Progress(models.Model):
match = re.search(to_find, self.score, re.IGNORECASE) match = re.search(to_find, self.score, re.IGNORECASE)
if match: if match:
updated_score = int(match.group('score')) + abs(score_to_add) updated_score = int(match.group("score")) + abs(score_to_add)
updated_possible = int(match.group('possible')) + abs(possible_to_add) updated_possible = int(match.group("possible")) + abs(possible_to_add)
new_score = ",".join([str(question.quiz), str(updated_score), str(updated_possible), ""]) new_score = ",".join(
[str(question.quiz), str(updated_score), str(updated_possible), ""]
)
# swap old score for the new one # swap old score for the new one
self.score = self.score.replace(match.group(), new_score) self.score = self.score.replace(match.group(), new_score)
@ -162,28 +220,33 @@ class Progress(models.Model):
else: else:
# if not present but existing, add with the points passed in # if not present but existing, add with the points passed in
self.score += ",".join([str(question.quiz), str(score_to_add), str(possible_to_add), ""]) self.score += ",".join(
[str(question.quiz), str(score_to_add), str(possible_to_add), ""]
)
self.save() self.save()
def show_exams(self): def show_exams(self):
if self.user.is_superuser: if self.user.is_superuser:
return Sitting.objects.filter(complete=True).order_by('-end') return Sitting.objects.filter(complete=True).order_by("-end")
else: else:
return Sitting.objects.filter(user=self.user, complete=True).order_by('-end') return Sitting.objects.filter(user=self.user, complete=True).order_by(
"-end"
)
class SittingManager(models.Manager): class SittingManager(models.Manager):
def new_sitting(self, user, quiz, course): def new_sitting(self, user, quiz, course):
if quiz.random_order is True: if quiz.random_order is True:
question_set = quiz.question_set.all().select_subclasses().order_by('?') question_set = quiz.question_set.all().select_subclasses().order_by("?")
else: else:
question_set = quiz.question_set.all().select_subclasses() question_set = quiz.question_set.all().select_subclasses()
question_set = [item.id for item in question_set] question_set = [item.id for item in question_set]
if len(question_set) == 0: if len(question_set) == 0:
raise ImproperlyConfigured('Question set of the quiz is empty. Please configure questions properly') raise ImproperlyConfigured(
"Question set of the quiz is empty. Please configure questions properly"
)
# if quiz.max_questions and quiz.max_questions < len(question_set): # if quiz.max_questions and quiz.max_questions < len(question_set):
# question_set = question_set[:quiz.max_questions] # question_set = question_set[:quiz.max_questions]
@ -191,43 +254,70 @@ class SittingManager(models.Manager):
questions = ",".join(map(str, question_set)) + "," questions = ",".join(map(str, question_set)) + ","
new_sitting = self.create( new_sitting = self.create(
user=user, quiz=quiz, course=course, question_order=questions, user=user,
question_list=questions, incorrect_questions="", quiz=quiz,
course=course,
question_order=questions,
question_list=questions,
incorrect_questions="",
current_score=0, current_score=0,
complete=False, complete=False,
user_answers='{}' user_answers="{}",
) )
return new_sitting return new_sitting
def user_sitting(self, user, quiz, course): def user_sitting(self, user, quiz, course):
if quiz.single_attempt is True and self.filter(user=user, quiz=quiz, course=course, complete=True).exists(): if (
quiz.single_attempt is True
and self.filter(user=user, quiz=quiz, course=course, complete=True).exists()
):
return False return False
try: try:
sitting = self.get(user=user, quiz=quiz, course=course, complete=False) sitting = self.get(user=user, quiz=quiz, course=course, complete=False)
except Sitting.DoesNotExist: except Sitting.DoesNotExist:
sitting = self.new_sitting(user, quiz, course) sitting = self.new_sitting(user, quiz, course)
except Sitting.MultipleObjectsReturned: except Sitting.MultipleObjectsReturned:
sitting = self.filter(user=user, quiz=quiz, course=course, complete=False)[0] sitting = self.filter(user=user, quiz=quiz, course=course, complete=False)[
0
]
return sitting return sitting
class Sitting(models.Model): class Sitting(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_("User"), on_delete=models.CASCADE) user = models.ForeignKey(
settings.AUTH_USER_MODEL, verbose_name=_("User"), on_delete=models.CASCADE
)
quiz = models.ForeignKey(Quiz, verbose_name=_("Quiz"), on_delete=models.CASCADE) quiz = models.ForeignKey(Quiz, verbose_name=_("Quiz"), on_delete=models.CASCADE)
course = models.ForeignKey(Course, null=True, verbose_name=_("Course"), on_delete=models.CASCADE) course = models.ForeignKey(
Course, null=True, verbose_name=_("Course"), on_delete=models.CASCADE
)
question_order = models.CharField(max_length=1024, verbose_name=_("Question Order"), question_order = models.CharField(
validators=[validate_comma_separated_integer_list]) max_length=1024,
verbose_name=_("Question Order"),
validators=[validate_comma_separated_integer_list],
)
question_list = models.CharField(max_length=1024, verbose_name=_("Question List"), question_list = models.CharField(
validators=[validate_comma_separated_integer_list]) max_length=1024,
verbose_name=_("Question List"),
validators=[validate_comma_separated_integer_list],
)
incorrect_questions = models.CharField(max_length=1024, blank=True, verbose_name=_("Incorrect questions"), incorrect_questions = models.CharField(
validators=[validate_comma_separated_integer_list]) max_length=1024,
blank=True,
verbose_name=_("Incorrect questions"),
validators=[validate_comma_separated_integer_list],
)
current_score = models.IntegerField(verbose_name=_("Current Score")) current_score = models.IntegerField(verbose_name=_("Current Score"))
complete = models.BooleanField(default=False, blank=False, verbose_name=_("Complete")) complete = models.BooleanField(
user_answers = models.TextField(blank=True, default='{}', verbose_name=_("User Answers")) default=False, blank=False, verbose_name=_("Complete")
)
user_answers = models.TextField(
blank=True, default="{}", verbose_name=_("User Answers")
)
start = models.DateTimeField(auto_now_add=True, verbose_name=_("Start")) start = models.DateTimeField(auto_now_add=True, verbose_name=_("Start"))
end = models.DateTimeField(null=True, blank=True, verbose_name=_("End")) end = models.DateTimeField(null=True, blank=True, verbose_name=_("End"))
@ -240,7 +330,7 @@ class Sitting(models.Model):
if not self.question_list: if not self.question_list:
return False return False
first, _ = self.question_list.split(',', 1) first, _ = self.question_list.split(",", 1)
question_id = int(first) question_id = int(first)
return Question.objects.get_subclass(id=question_id) return Question.objects.get_subclass(id=question_id)
@ -248,7 +338,7 @@ class Sitting(models.Model):
if not self.question_list: if not self.question_list:
return return
_, others = self.question_list.split(',', 1) _, others = self.question_list.split(",", 1)
self.question_list = others self.question_list = others
self.save() self.save()
@ -261,14 +351,14 @@ class Sitting(models.Model):
return self.current_score return self.current_score
def _question_ids(self): def _question_ids(self):
return [int(n) for n in self.question_order.split(',') if n] return [int(n) for n in self.question_order.split(",") if n]
@property @property
def get_percent_correct(self): def get_percent_correct(self):
dividend = float(self.current_score) dividend = float(self.current_score)
divisor = len(self._question_ids()) divisor = len(self._question_ids())
if divisor < 1: if divisor < 1:
return 0 # prevent divide by zero error return 0 # prevent divide by zero error
if dividend > divisor: if dividend > divisor:
return 100 return 100
@ -287,7 +377,7 @@ class Sitting(models.Model):
def add_incorrect_question(self, question): def add_incorrect_question(self, question):
if len(self.incorrect_questions) > 0: if len(self.incorrect_questions) > 0:
self.incorrect_questions += ',' self.incorrect_questions += ","
self.incorrect_questions += str(question.id) + "," self.incorrect_questions += str(question.id) + ","
if self.complete: if self.complete:
self.add_to_score(-1) self.add_to_score(-1)
@ -295,12 +385,12 @@ class Sitting(models.Model):
@property @property
def get_incorrect_questions(self): def get_incorrect_questions(self):
return [int(q) for q in self.incorrect_questions.split(',') if q] return [int(q) for q in self.incorrect_questions.split(",") if q]
def remove_incorrect_question(self, question): def remove_incorrect_question(self, question):
current = self.get_incorrect_questions current = self.get_incorrect_questions
current.remove(question.id) current.remove(question.id)
self.incorrect_questions = ','.join(map(str, current)) self.incorrect_questions = ",".join(map(str, current))
self.add_to_score(1) self.add_to_score(1)
self.save() self.save()
@ -323,7 +413,10 @@ class Sitting(models.Model):
def get_questions(self, with_answers=False): def get_questions(self, with_answers=False):
question_ids = self._question_ids() question_ids = self._question_ids()
questions = sorted(self.quiz.question_set.filter(id__in=question_ids).select_subclasses(), key=lambda q: question_ids.index(q.id)) questions = sorted(
self.quiz.question_set.filter(id__in=question_ids).select_subclasses(),
key=lambda q: question_ids.index(q.id),
)
if with_answers: if with_answers:
user_answers = json.loads(self.user_answers) user_answers = json.loads(self.user_answers)
@ -348,12 +441,21 @@ class Sitting(models.Model):
class Question(models.Model): class Question(models.Model):
quiz = models.ManyToManyField(Quiz, verbose_name=_("Quiz"), blank=True) quiz = models.ManyToManyField(Quiz, verbose_name=_("Quiz"), blank=True)
figure = models.ImageField(upload_to='uploads/%Y/%m/%d', blank=True, null=True, verbose_name=_("Figure")) figure = models.ImageField(
content = models.CharField(max_length=1000, blank=False, upload_to="uploads/%Y/%m/%d", blank=True, null=True, verbose_name=_("Figure")
help_text=_("Enter the question text that you want displayed"), verbose_name=_('Question')) )
explanation = models.TextField(max_length=2000, blank=True, content = models.CharField(
max_length=1000,
blank=False,
help_text=_("Enter the question text that you want displayed"),
verbose_name=_("Question"),
)
explanation = models.TextField(
max_length=2000,
blank=True,
help_text=_("Explanation to be shown after the question has been answered."), help_text=_("Explanation to be shown after the question has been answered."),
verbose_name=_('Explanation')) verbose_name=_("Explanation"),
)
objects = InheritanceManager() objects = InheritanceManager()
@ -366,12 +468,16 @@ class Question(models.Model):
class MCQuestion(Question): class MCQuestion(Question):
choice_order = models.CharField( choice_order = models.CharField(
max_length=30, null=True, blank=True, max_length=30,
null=True,
blank=True,
choices=CHOICE_ORDER_OPTIONS, choices=CHOICE_ORDER_OPTIONS,
help_text=_("The order in which multichoice choice options are displayed to the user"), help_text=_(
verbose_name=_("Choice Order")) "The order in which multichoice choice options are displayed to the user"
),
verbose_name=_("Choice Order"),
)
def check_if_correct(self, guess): def check_if_correct(self, guess):
answer = Choice.objects.get(id=guess) answer = Choice.objects.get(id=guess)
@ -382,11 +488,11 @@ class MCQuestion(Question):
return False return False
def order_choices(self, queryset): def order_choices(self, queryset):
if self.choice_order == 'content': if self.choice_order == "content":
return queryset.order_by('choice') return queryset.order_by("choice")
if self.choice_order == 'random': if self.choice_order == "random":
return queryset.order_by('?') return queryset.order_by("?")
if self.choice_order == 'none': if self.choice_order == "none":
return queryset.order_by() return queryset.order_by()
return queryset return queryset
@ -394,8 +500,10 @@ class MCQuestion(Question):
return self.order_choices(Choice.objects.filter(question=self)) return self.order_choices(Choice.objects.filter(question=self))
def get_choices_list(self): def get_choices_list(self):
return [(choice.id, choice.choice) for choice in return [
self.order_choices(Choice.objects.filter(question=self))] (choice.id, choice.choice)
for choice in self.order_choices(Choice.objects.filter(question=self))
]
def answer_choice_to_string(self, guess): def answer_choice_to_string(self, guess):
return Choice.objects.get(id=guess).choice return Choice.objects.get(id=guess).choice
@ -406,15 +514,23 @@ class MCQuestion(Question):
class Choice(models.Model): class Choice(models.Model):
question = models.ForeignKey(MCQuestion, verbose_name=_("Question"), on_delete=models.CASCADE) question = models.ForeignKey(
MCQuestion, verbose_name=_("Question"), on_delete=models.CASCADE
)
choice = models.CharField(max_length=1000, blank=False, choice = models.CharField(
help_text=_("Enter the choice text that you want displayed"), max_length=1000,
verbose_name=_("Content")) blank=False,
help_text=_("Enter the choice text that you want displayed"),
verbose_name=_("Content"),
)
correct = models.BooleanField(blank=False, default=False, correct = models.BooleanField(
help_text=_("Is this a correct answer?"), blank=False,
verbose_name=_("Correct")) default=False,
help_text=_("Is this a correct answer?"),
verbose_name=_("Correct"),
)
def __str__(self): def __str__(self):
return self.choice return self.choice
@ -425,7 +541,6 @@ class Choice(models.Model):
class Essay_Question(Question): class Essay_Question(Question):
def check_if_correct(self, guess): def check_if_correct(self, guess):
return False return False

View File

@ -2,21 +2,23 @@ from django.urls import path
from .views import * from .views import *
urlpatterns = [ urlpatterns = [
path("<slug>/quizzes/", quiz_list, name="quiz_index"),
path('<slug>/quizzes/', quiz_list, name='quiz_index'), path("progress/", view=QuizUserProgressView.as_view(), name="quiz_progress"),
path('progress/', view=QuizUserProgressView.as_view(), name='quiz_progress'),
# path('marking/<int:pk>/', view=QuizMarkingList.as_view(), name='quiz_marking'), # path('marking/<int:pk>/', view=QuizMarkingList.as_view(), name='quiz_marking'),
path('marking_list/', view=QuizMarkingList.as_view(), name='quiz_marking'), path("marking_list/", view=QuizMarkingList.as_view(), name="quiz_marking"),
path(
path('marking/<int:pk>/', view=QuizMarkingDetail.as_view(), name='quiz_marking_detail'), "marking/<int:pk>/",
view=QuizMarkingDetail.as_view(),
path('<int:pk>/<slug>/take/', view=QuizTake.as_view(), name='quiz_take'), name="quiz_marking_detail",
),
path('<slug>/quiz_add/', QuizCreateView.as_view(), name='quiz_create'), path("<int:pk>/<slug>/take/", view=QuizTake.as_view(), name="quiz_take"),
path('<slug>/<int:pk>/add/', QuizUpdateView.as_view(), name='quiz_update'), path("<slug>/quiz_add/", QuizCreateView.as_view(), name="quiz_create"),
path('<slug>/<int:pk>/delete/', quiz_delete, name='quiz_delete'), path("<slug>/<int:pk>/add/", QuizUpdateView.as_view(), name="quiz_update"),
path('mc-question/add/<slug>/<int:quiz_id>/', MCQuestionCreate.as_view(), name='mc_create'), path("<slug>/<int:pk>/delete/", quiz_delete, name="quiz_delete"),
path(
"mc-question/add/<slug>/<int:quiz_id>/",
MCQuestionCreate.as_view(),
name="mc_create",
),
# path('mc-question/add/<int:pk>/<quiz_pk>/', MCQuestionCreate.as_view(), name='mc_create'), # path('mc-question/add/<int:pk>/<quiz_pk>/', MCQuestionCreate.as_view(), name='mc_create'),
] ]

View File

@ -1,4 +1,4 @@
import datetime import datetime
import os import os
import random import random
import string import string
@ -7,12 +7,12 @@ from django.utils.text import slugify
def random_string_generator(size=10, chars=string.ascii_lowercase + string.digits): def random_string_generator(size=10, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size)) return "".join(random.choice(chars) for _ in range(size))
def unique_slug_generator(instance, new_slug=None): def unique_slug_generator(instance, new_slug=None):
""" """
This is for a Django project and it assumes your instance This is for a Django project and it assumes your instance
has a model with a slug field and a title character (char) field. has a model with a slug field and a title character (char) field.
""" """
if new_slug is not None: if new_slug is not None:
@ -24,8 +24,7 @@ def unique_slug_generator(instance, new_slug=None):
qs_exists = Klass.objects.filter(slug=slug).exists() qs_exists = Klass.objects.filter(slug=slug).exists()
if qs_exists: if qs_exists:
new_slug = "{slug}-{randstr}".format( new_slug = "{slug}-{randstr}".format(
slug=slug, slug=slug, randstr=random_string_generator(size=4)
randstr=random_string_generator(size=4) )
)
return unique_slug_generator(instance, new_slug=new_slug) return unique_slug_generator(instance, new_slug=new_slug)
return slug return slug

View File

@ -4,7 +4,16 @@ from django.contrib.auth.decorators import login_required, permission_required
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404, render, redirect from django.shortcuts import get_object_or_404, render, redirect
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.generic import DetailView, ListView, TemplateView, FormView, CreateView, FormView, DeleteView, UpdateView from django.views.generic import (
DetailView,
ListView,
TemplateView,
FormView,
CreateView,
FormView,
DeleteView,
UpdateView,
)
from django.contrib import messages from django.contrib import messages
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.db import transaction from django.db import transaction
@ -16,58 +25,62 @@ from .models import *
from .forms import * from .forms import *
@method_decorator([login_required, lecturer_required], name='dispatch') @method_decorator([login_required, lecturer_required], name="dispatch")
class QuizCreateView(CreateView): class QuizCreateView(CreateView):
model = Quiz model = Quiz
form_class = QuizAddForm form_class = QuizAddForm
def get_context_data(self, *args, **kwargs): def get_context_data(self, *args, **kwargs):
context = super(QuizCreateView, self).get_context_data(**kwargs) context = super(QuizCreateView, self).get_context_data(**kwargs)
context['course'] = Course.objects.get(slug=self.kwargs['slug']) context["course"] = Course.objects.get(slug=self.kwargs["slug"])
if self.request.POST: if self.request.POST:
context['form'] = QuizAddForm(self.request.POST) context["form"] = QuizAddForm(self.request.POST)
# context['quiz'] = self.request.POST.get('quiz') # context['quiz'] = self.request.POST.get('quiz')
else: else:
context['form'] = QuizAddForm(initial={'course': Course.objects.get(slug=self.kwargs['slug'])}) context["form"] = QuizAddForm(
initial={"course": Course.objects.get(slug=self.kwargs["slug"])}
)
return context return context
def form_valid(self, form, **kwargs): def form_valid(self, form, **kwargs):
context = self.get_context_data() context = self.get_context_data()
form = context['form'] form = context["form"]
with transaction.atomic(): with transaction.atomic():
self.object = form.save() self.object = form.save()
if form.is_valid(): if form.is_valid():
form.instance = self.object form.instance = self.object
form.save() form.save()
return redirect('mc_create', slug=self.kwargs['slug'], quiz_id=form.instance.id) return redirect(
"mc_create", slug=self.kwargs["slug"], quiz_id=form.instance.id
)
return super(QuizCreateView, self).form_invalid(form) return super(QuizCreateView, self).form_invalid(form)
@method_decorator([login_required, lecturer_required], name='dispatch') @method_decorator([login_required, lecturer_required], name="dispatch")
class QuizUpdateView(UpdateView): class QuizUpdateView(UpdateView):
model = Quiz model = Quiz
form_class = QuizAddForm form_class = QuizAddForm
def get_context_data(self, *args, **kwargs): def get_context_data(self, *args, **kwargs):
context = super(QuizUpdateView, self).get_context_data(**kwargs) context = super(QuizUpdateView, self).get_context_data(**kwargs)
context['course'] = Course.objects.get(slug=self.kwargs['slug']) context["course"] = Course.objects.get(slug=self.kwargs["slug"])
quiz = Quiz.objects.get(pk=self.kwargs['pk']) quiz = Quiz.objects.get(pk=self.kwargs["pk"])
if self.request.POST: if self.request.POST:
context['form'] = QuizAddForm(self.request.POST, instance=quiz) context["form"] = QuizAddForm(self.request.POST, instance=quiz)
else: else:
context['form'] = QuizAddForm(instance=quiz) context["form"] = QuizAddForm(instance=quiz)
return context return context
def form_valid(self, form, **kwargs): def form_valid(self, form, **kwargs):
context = self.get_context_data() context = self.get_context_data()
course = context['course'] course = context["course"]
form = context['form'] form = context["form"]
with transaction.atomic(): with transaction.atomic():
self.object = form.save() self.object = form.save()
if form.is_valid(): if form.is_valid():
form.instance = self.object form.instance = self.object
form.save() form.save()
return redirect('quiz_index', course.slug) return redirect("quiz_index", course.slug)
return super(QuizUpdateView, self).form_invalid(form) return super(QuizUpdateView, self).form_invalid(form)
@ -77,54 +90,62 @@ def quiz_delete(request, slug, pk):
quiz = Quiz.objects.get(pk=pk) quiz = Quiz.objects.get(pk=pk)
course = Course.objects.get(slug=slug) course = Course.objects.get(slug=slug)
quiz.delete() quiz.delete()
messages.success(request, f'successfuly deleted.') messages.success(request, f"successfuly deleted.")
return redirect('quiz_index', quiz.course.slug) return redirect("quiz_index", quiz.course.slug)
@method_decorator([login_required, lecturer_required], name='dispatch') @method_decorator([login_required, lecturer_required], name="dispatch")
class MCQuestionCreate(CreateView): class MCQuestionCreate(CreateView):
model = MCQuestion model = MCQuestion
form_class = MCQuestionForm form_class = MCQuestionForm
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(MCQuestionCreate, self).get_context_data(**kwargs) context = super(MCQuestionCreate, self).get_context_data(**kwargs)
context['course'] = Course.objects.get(slug=self.kwargs['slug']) context["course"] = Course.objects.get(slug=self.kwargs["slug"])
context['quiz_obj'] = Quiz.objects.get(id=self.kwargs['quiz_id']) context["quiz_obj"] = Quiz.objects.get(id=self.kwargs["quiz_id"])
context['quizQuestions'] = Question.objects.filter(quiz=self.kwargs['quiz_id']).count() context["quizQuestions"] = Question.objects.filter(
quiz=self.kwargs["quiz_id"]
).count()
if self.request.POST: if self.request.POST:
context['form'] = MCQuestionForm(self.request.POST) context["form"] = MCQuestionForm(self.request.POST)
context['formset'] = MCQuestionFormSet(self.request.POST) context["formset"] = MCQuestionFormSet(self.request.POST)
else: else:
context['form'] = MCQuestionForm(initial={'quiz': self.kwargs['quiz_id']}) context["form"] = MCQuestionForm(initial={"quiz": self.kwargs["quiz_id"]})
context['formset'] = MCQuestionFormSet() context["formset"] = MCQuestionFormSet()
return context return context
def form_valid(self, form): def form_valid(self, form):
context = self.get_context_data() context = self.get_context_data()
formset = context['formset'] formset = context["formset"]
course = context['course'] course = context["course"]
with transaction.atomic(): with transaction.atomic():
form.instance.question = self.request.POST.get('content') form.instance.question = self.request.POST.get("content")
self.object = form.save() self.object = form.save()
if formset.is_valid(): if formset.is_valid():
formset.instance = self.object formset.instance = self.object
formset.save() formset.save()
if "another" in self.request.POST: if "another" in self.request.POST:
return redirect('mc_create', slug=self.kwargs['slug'], quiz_id=self.kwargs['quiz_id']) return redirect(
return redirect('quiz_index', course.slug) "mc_create",
slug=self.kwargs["slug"],
quiz_id=self.kwargs["quiz_id"],
)
return redirect("quiz_index", course.slug)
return super(MCQuestionCreate, self).form_invalid(form) return super(MCQuestionCreate, self).form_invalid(form)
@login_required @login_required
def quiz_list(request, slug): def quiz_list(request, slug):
quizzes = Quiz.objects.filter(course__slug = slug).order_by('-timestamp') quizzes = Quiz.objects.filter(course__slug=slug).order_by("-timestamp")
course = Course.objects.get(slug = slug) course = Course.objects.get(slug=slug)
return render(request, 'quiz/quiz_list.html', {'quizzes': quizzes, 'course': course}) return render(
request, "quiz/quiz_list.html", {"quizzes": quizzes, "course": course}
)
# return render(request, 'quiz/quiz_list.html', {'quizzes': quizzes}) # return render(request, 'quiz/quiz_list.html', {'quizzes': quizzes})
@method_decorator([login_required, lecturer_required], name='dispatch') @method_decorator([login_required, lecturer_required], name="dispatch")
class QuizMarkerMixin(object): class QuizMarkerMixin(object):
@method_decorator(login_required) @method_decorator(login_required)
# @method_decorator(permission_required('quiz.view_sittings')) # @method_decorator(permission_required('quiz.view_sittings'))
@ -136,16 +157,16 @@ class QuizMarkerMixin(object):
class SittingFilterTitleMixin(object): class SittingFilterTitleMixin(object):
def get_queryset(self): def get_queryset(self):
queryset = super(SittingFilterTitleMixin, self).get_queryset() queryset = super(SittingFilterTitleMixin, self).get_queryset()
quiz_filter = self.request.GET.get('quiz_filter') quiz_filter = self.request.GET.get("quiz_filter")
if quiz_filter: if quiz_filter:
queryset = queryset.filter(quiz__title__icontains=quiz_filter) queryset = queryset.filter(quiz__title__icontains=quiz_filter)
return queryset return queryset
@method_decorator([login_required], name='dispatch') @method_decorator([login_required], name="dispatch")
class QuizUserProgressView(TemplateView): class QuizUserProgressView(TemplateView):
template_name = 'progress.html' template_name = "progress.html"
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
return super(QuizUserProgressView, self).dispatch(request, *args, **kwargs) return super(QuizUserProgressView, self).dispatch(request, *args, **kwargs)
@ -153,16 +174,19 @@ class QuizUserProgressView(TemplateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(QuizUserProgressView, self).get_context_data(**kwargs) context = super(QuizUserProgressView, self).get_context_data(**kwargs)
progress, c = Progress.objects.get_or_create(user=self.request.user) progress, c = Progress.objects.get_or_create(user=self.request.user)
context['cat_scores'] = progress.list_all_cat_scores context["cat_scores"] = progress.list_all_cat_scores
context['exams'] = progress.show_exams() context["exams"] = progress.show_exams()
context['exams_counter'] = progress.show_exams().count() context["exams_counter"] = progress.show_exams().count()
return context return context
from result.models import TakenCourse from result.models import TakenCourse
@method_decorator([login_required, lecturer_required], name='dispatch')
@method_decorator([login_required, lecturer_required], name="dispatch")
class QuizMarkingList(QuizMarkerMixin, SittingFilterTitleMixin, ListView): class QuizMarkingList(QuizMarkerMixin, SittingFilterTitleMixin, ListView):
model = Sitting model = Sitting
# def get_context_data(self, **kwargs): # def get_context_data(self, **kwargs):
# context = super(QuizMarkingList, self).get_context_data(**kwargs) # context = super(QuizMarkingList, self).get_context_data(**kwargs)
# context['queryset_counter'] = super(QuizMarkingList, self).get_queryset().filter(complete=True).filter(course__allocated_course__lecturer__pk=self.request.user.id).count() # context['queryset_counter'] = super(QuizMarkingList, self).get_queryset().filter(complete=True).filter(course__allocated_course__lecturer__pk=self.request.user.id).count()
@ -172,24 +196,31 @@ class QuizMarkingList(QuizMarkerMixin, SittingFilterTitleMixin, ListView):
if self.request.user.is_superuser: if self.request.user.is_superuser:
queryset = super(QuizMarkingList, self).get_queryset().filter(complete=True) queryset = super(QuizMarkingList, self).get_queryset().filter(complete=True)
else: else:
queryset = super(QuizMarkingList, self).get_queryset().filter(quiz__course__allocated_course__lecturer__pk=self.request.user.id).filter(complete=True) queryset = (
super(QuizMarkingList, self)
.get_queryset()
.filter(
quiz__course__allocated_course__lecturer__pk=self.request.user.id
)
.filter(complete=True)
)
# search by user # search by user
user_filter = self.request.GET.get('user_filter') user_filter = self.request.GET.get("user_filter")
if user_filter: if user_filter:
queryset = queryset.filter(user__username__icontains=user_filter) queryset = queryset.filter(user__username__icontains=user_filter)
return queryset return queryset
@method_decorator([login_required, lecturer_required], name='dispatch') @method_decorator([login_required, lecturer_required], name="dispatch")
class QuizMarkingDetail(QuizMarkerMixin, DetailView): class QuizMarkingDetail(QuizMarkerMixin, DetailView):
model = Sitting model = Sitting
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
sitting = self.get_object() sitting = self.get_object()
q_to_toggle = request.POST.get('qid', None) q_to_toggle = request.POST.get("qid", None)
if q_to_toggle: if q_to_toggle:
q = Question.objects.get_subclass(id=int(q_to_toggle)) q = Question.objects.get_subclass(id=int(q_to_toggle))
if int(q_to_toggle) in sitting.get_incorrect_questions: if int(q_to_toggle) in sitting.get_incorrect_questions:
@ -201,37 +232,42 @@ class QuizMarkingDetail(QuizMarkerMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(QuizMarkingDetail, self).get_context_data(**kwargs) context = super(QuizMarkingDetail, self).get_context_data(**kwargs)
context['questions'] = context['sitting'].get_questions(with_answers=True) context["questions"] = context["sitting"].get_questions(with_answers=True)
return context return context
# @method_decorator([login_required, student_required], name='dispatch') # @method_decorator([login_required, student_required], name='dispatch')
@method_decorator([login_required], name='dispatch') @method_decorator([login_required], name="dispatch")
class QuizTake(FormView): class QuizTake(FormView):
form_class = QuestionForm form_class = QuestionForm
template_name = 'question.html' template_name = "question.html"
result_template_name = 'result.html' result_template_name = "result.html"
# single_complete_template_name = 'single_complete.html' # single_complete_template_name = 'single_complete.html'
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
self.quiz = get_object_or_404(Quiz, slug=self.kwargs['slug']) self.quiz = get_object_or_404(Quiz, slug=self.kwargs["slug"])
self.course = get_object_or_404(Course, pk=self.kwargs['pk']) self.course = get_object_or_404(Course, pk=self.kwargs["pk"])
quizQuestions = Question.objects.filter(quiz=self.quiz).count() quizQuestions = Question.objects.filter(quiz=self.quiz).count()
course = get_object_or_404(Course, pk=self.kwargs['pk']) course = get_object_or_404(Course, pk=self.kwargs["pk"])
if quizQuestions <= 0: if quizQuestions <= 0:
messages.warning(request, f'Question set of the quiz is empty. try later!') messages.warning(request, f"Question set of the quiz is empty. try later!")
return redirect('quiz_index', self.course.slug) return redirect("quiz_index", self.course.slug)
if self.quiz.draft and not request.user.has_perm('quiz.change_quiz'): if self.quiz.draft and not request.user.has_perm("quiz.change_quiz"):
raise PermissionDenied raise PermissionDenied
self.sitting = Sitting.objects.user_sitting(request.user, self.quiz, self.course) self.sitting = Sitting.objects.user_sitting(
request.user, self.quiz, self.course
)
if self.sitting is False: if self.sitting is False:
# return render(request, self.single_complete_template_name) # return render(request, self.single_complete_template_name)
messages.info(request, f'You have already sat this exam and only one sitting is permitted') messages.info(
return redirect('quiz_index', self.course.slug) request,
f"You have already sat this exam and only one sitting is permitted",
)
return redirect("quiz_index", self.course.slug)
return super(QuizTake, self).dispatch(request, *args, **kwargs) return super(QuizTake, self).dispatch(request, *args, **kwargs)
@ -262,18 +298,18 @@ class QuizTake(FormView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(QuizTake, self).get_context_data(**kwargs) context = super(QuizTake, self).get_context_data(**kwargs)
context['question'] = self.question context["question"] = self.question
context['quiz'] = self.quiz context["quiz"] = self.quiz
context['course'] = get_object_or_404(Course, pk=self.kwargs['pk']) context["course"] = get_object_or_404(Course, pk=self.kwargs["pk"])
if hasattr(self, 'previous'): if hasattr(self, "previous"):
context['previous'] = self.previous context["previous"] = self.previous
if hasattr(self, 'progress'): if hasattr(self, "progress"):
context['progress'] = self.progress context["progress"] = self.progress
return context return context
def form_valid_user(self, form): def form_valid_user(self, form):
progress, c = Progress.objects.get_or_create(user=self.request.user) progress, c = Progress.objects.get_or_create(user=self.request.user)
guess = form.cleaned_data['answers'] guess = form.cleaned_data["answers"]
is_correct = self.question.check_if_correct(guess) is_correct = self.question.check_if_correct(guess)
if is_correct is True: if is_correct is True:
@ -285,11 +321,11 @@ class QuizTake(FormView):
if self.quiz.answers_at_end is not True: if self.quiz.answers_at_end is not True:
self.previous = { self.previous = {
'previous_answer': guess, "previous_answer": guess,
'previous_outcome': is_correct, "previous_outcome": is_correct,
'previous_question': self.question, "previous_question": self.question,
'answers': self.question.get_choices(), "answers": self.question.get_choices(),
'question_type': {self.question.__class__.__name__: True} "question_type": {self.question.__class__.__name__: True},
} }
else: else:
self.previous = {} self.previous = {}
@ -299,23 +335,27 @@ class QuizTake(FormView):
def final_result_user(self): def final_result_user(self):
results = { results = {
'course': get_object_or_404(Course, pk=self.kwargs['pk']), "course": get_object_or_404(Course, pk=self.kwargs["pk"]),
'quiz': self.quiz, "quiz": self.quiz,
'score': self.sitting.get_current_score, "score": self.sitting.get_current_score,
'max_score': self.sitting.get_max_score, "max_score": self.sitting.get_max_score,
'percent': self.sitting.get_percent_correct, "percent": self.sitting.get_percent_correct,
'sitting': self.sitting, "sitting": self.sitting,
'previous': self.previous, "previous": self.previous,
'course': get_object_or_404(Course, pk=self.kwargs['pk']) "course": get_object_or_404(Course, pk=self.kwargs["pk"]),
} }
self.sitting.mark_quiz_complete() self.sitting.mark_quiz_complete()
if self.quiz.answers_at_end: if self.quiz.answers_at_end:
results['questions'] = self.sitting.get_questions(with_answers=True) results["questions"] = self.sitting.get_questions(with_answers=True)
results['incorrect_questions'] = self.sitting.get_incorrect_questions results["incorrect_questions"] = self.sitting.get_incorrect_questions
if self.quiz.exam_paper is False or self.request.user.is_superuser or self.request.user.is_lecturer : if (
self.quiz.exam_paper is False
or self.request.user.is_superuser
or self.request.user.is_lecturer
):
self.sitting.delete() self.sitting.delete()
return render(self.request, self.result_template_name, results) return render(self.request, self.result_template_name, results)

View File

@ -6,8 +6,16 @@ from .models import TakenCourse, Result
class ScoreAdmin(admin.ModelAdmin): class ScoreAdmin(admin.ModelAdmin):
list_display = [ list_display = [
'student', 'course', 'assignment', 'mid_exam', 'quiz', "student",
'attendance', 'final_exam', 'total', 'grade', 'comment' "course",
"assignment",
"mid_exam",
"quiz",
"attendance",
"final_exam",
"total",
"grade",
"comment",
] ]

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class ResultConfig(AppConfig): class ResultConfig(AppConfig):
name = 'result' name = "result"

View File

@ -6,13 +6,13 @@ from app.models import Session, Semester
from course.models import Course from course.models import Course
YEARS = ( YEARS = (
(1, '1'), (1, "1"),
(2, '2'), (2, "2"),
(3, '3'), (3, "3"),
(4, '4'), (4, "4"),
(4, '5'), (4, "5"),
(4, '6'), (4, "6"),
) )
# LEVEL_COURSE = "Level course" # LEVEL_COURSE = "Level course"
BACHLOAR_DEGREE = "Bachloar" BACHLOAR_DEGREE = "Bachloar"
@ -48,18 +48,18 @@ F = "F"
NG = "NG" NG = "NG"
GRADE = ( GRADE = (
(A_plus, "A+"), (A_plus, "A+"),
(A, "A"), (A, "A"),
(A_minus, "A-"), (A_minus, "A-"),
(B_plus, "B+"), (B_plus, "B+"),
(B, "B"), (B, "B"),
(B_minus, "B-"), (B_minus, "B-"),
(C_plus, "C+"), (C_plus, "C+"),
(C, "C"), (C, "C"),
(C_minus, "C-"), (C_minus, "C-"),
(D, "D"), (D, "D"),
(F, "F"), (F, "F"),
(NG, "NG"), (NG, "NG"),
) )
PASS = "PASS" PASS = "PASS"
@ -84,7 +84,7 @@ class TakenCourseManager(models.Manager):
else: else:
cart_obj = Cart.objects.new(user=request.user) cart_obj = Cart.objects.new(user=request.user)
new_obj = True new_obj = True
request.session['cart_id'] = cart_obj.id request.session["cart_id"] = cart_obj.id
return cart_obj, new_obj return cart_obj, new_obj
def new(self, user=None): def new(self, user=None):
@ -97,7 +97,9 @@ class TakenCourseManager(models.Manager):
class TakenCourse(models.Model): class TakenCourse(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE) student = models.ForeignKey(Student, on_delete=models.CASCADE)
course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='taken_courses') course = models.ForeignKey(
Course, on_delete=models.CASCADE, related_name="taken_courses"
)
assignment = models.DecimalField(max_digits=5, decimal_places=2, default=0.0) assignment = models.DecimalField(max_digits=5, decimal_places=2, default=0.0)
mid_exam = models.DecimalField(max_digits=5, decimal_places=2, default=0.0) mid_exam = models.DecimalField(max_digits=5, decimal_places=2, default=0.0)
quiz = models.DecimalField(max_digits=5, decimal_places=2, default=0.0) quiz = models.DecimalField(max_digits=5, decimal_places=2, default=0.0)
@ -109,14 +111,20 @@ class TakenCourse(models.Model):
comment = models.CharField(choices=COMMENT, max_length=200, blank=True) comment = models.CharField(choices=COMMENT, max_length=200, blank=True)
def get_absolute_url(self): def get_absolute_url(self):
return reverse('course_detail', kwargs={'slug': self.course.slug}) return reverse("course_detail", kwargs={"slug": self.course.slug})
def __str__(self): def __str__(self):
return "{0} ({1})".format(self.course.title, self.course.code) return "{0} ({1})".format(self.course.title, self.course.code)
# @staticmethod # @staticmethod
def get_total(self, assignment, mid_exam, quiz, attendance, final_exam): def get_total(self, assignment, mid_exam, quiz, attendance, final_exam):
return float(assignment) + float(mid_exam) + float(quiz) + float(attendance) + float(final_exam) return (
float(assignment)
+ float(mid_exam)
+ float(quiz)
+ float(attendance)
+ float(final_exam)
)
# @staticmethod # @staticmethod
def get_grade(self, total): def get_grade(self, total):
@ -191,7 +199,11 @@ class TakenCourse(models.Model):
def calculate_gpa(self, total_credit_in_semester): def calculate_gpa(self, total_credit_in_semester):
current_semester = Semester.objects.get(is_current_semester=True) current_semester = Semester.objects.get(is_current_semester=True)
student = TakenCourse.objects.filter(student=self.student, course__level=self.student.level, course__semester=current_semester) student = TakenCourse.objects.filter(
student=self.student,
course__level=self.student.level,
course__semester=current_semester,
)
p = 0 p = 0
point = 0 point = 0
for i in student: for i in student:
@ -220,14 +232,16 @@ class TakenCourse(models.Model):
point = 0 point = 0
p += int(credit) * point p += int(credit) * point
try: try:
gpa = (p / total_credit_in_semester) gpa = p / total_credit_in_semester
return round(gpa, 2) return round(gpa, 2)
except ZeroDivisionError: except ZeroDivisionError:
return 0 return 0
def calculate_cgpa(self): def calculate_cgpa(self):
current_semester = Semester.objects.get(is_current_semester=True) current_semester = Semester.objects.get(is_current_semester=True)
previousResult = Result.objects.filter(student__id=self.student.id, level__lt=self.student.level) previousResult = Result.objects.filter(
student__id=self.student.id, level__lt=self.student.level
)
previousCGPA = 0 previousCGPA = 0
for i in previousResult: for i in previousResult:
if i.cgpa is not None: if i.cgpa is not None:
@ -237,18 +251,24 @@ class TakenCourse(models.Model):
first_sem_gpa = 0.0 first_sem_gpa = 0.0
sec_sem_gpa = 0.0 sec_sem_gpa = 0.0
try: try:
first_sem_result = Result.objects.get(student=self.student.id, semester=FIRST, level=self.student.level) first_sem_result = Result.objects.get(
student=self.student.id, semester=FIRST, level=self.student.level
)
first_sem_gpa += first_sem_result.gpa first_sem_gpa += first_sem_result.gpa
except: except:
first_sem_gpa = 0 first_sem_gpa = 0
try: try:
sec_sem_result = Result.objects.get(student=self.student.id, semester=SECOND, level=self.student.level) sec_sem_result = Result.objects.get(
student=self.student.id, semester=SECOND, level=self.student.level
)
sec_sem_gpa += sec_sem_result.gpa sec_sem_gpa += sec_sem_result.gpa
except: except:
sec_sem_gpa = 0 sec_sem_gpa = 0
taken_courses = TakenCourse.objects.filter(student=self.student, student__level=self.student.level) taken_courses = TakenCourse.objects.filter(
student=self.student, student__level=self.student.level
)
TCC = 0 TCC = 0
TCP = 0 TCP = 0
for i in taken_courses: for i in taken_courses:

View File

@ -1,17 +1,21 @@
from django.urls import path from django.urls import path
from .views import ( from .views import (
add_score, add_score_for, grade_result, assessment_result, add_score,
course_registration_form, result_sheet_pdf_view add_score_for,
grade_result,
assessment_result,
course_registration_form,
result_sheet_pdf_view,
) )
urlpatterns = [ urlpatterns = [
path('manage-score/', add_score, name='add_score'), path("manage-score/", add_score, name="add_score"),
path('manage-score/<int:id>/', add_score_for, name='add_score_for'), path("manage-score/<int:id>/", add_score_for, name="add_score_for"),
path("grade/", grade_result, name="grade_results"),
path('grade/', grade_result, name="grade_results"), path("assessment/", assessment_result, name="ass_results"),
path('assessment/', assessment_result, name="ass_results"), path("result/print/<int:id>/", result_sheet_pdf_view, name="result_sheet_pdf_view"),
path(
path('result/print/<int:id>/', result_sheet_pdf_view, name='result_sheet_pdf_view'), "registration/form/", course_registration_form, name="course_registration_form"
path('registration/form/', course_registration_form, name='course_registration_form'), ),
] ]

View File

@ -12,13 +12,21 @@ from course.models import Course
from accounts.decorators import lecturer_required, student_required from accounts.decorators import lecturer_required, student_required
from .models import TakenCourse, Result from .models import TakenCourse, Result
#pdf # pdf
from django.core.files.storage import FileSystemStorage from django.core.files.storage import FileSystemStorage
from django.http import HttpResponse, JsonResponse from django.http import HttpResponse, JsonResponse
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Image, LongTable from reportlab.platypus import (
SimpleDocTemplate,
Paragraph,
Spacer,
Table,
TableStyle,
Image,
LongTable,
)
from reportlab.lib.styles import getSampleStyleSheet, black, ParagraphStyle from reportlab.lib.styles import getSampleStyleSheet, black, ParagraphStyle
from reportlab.lib.enums import TA_JUSTIFY,TA_LEFT,TA_CENTER,TA_RIGHT from reportlab.lib.enums import TA_JUSTIFY, TA_LEFT, TA_CENTER, TA_RIGHT
from reportlab.platypus.tables import Table from reportlab.platypus.tables import Table
from reportlab.lib.units import inch from reportlab.lib.units import inch
from reportlab.lib import colors from reportlab.lib import colors
@ -26,27 +34,32 @@ from .models import *
cm = 2.54 cm = 2.54
# ######################################################## # ########################################################
# Score Add & Add for # Score Add & Add for
# ######################################################## # ########################################################
@login_required @login_required
@lecturer_required @lecturer_required
def add_score(request): def add_score(request):
""" """
Shows a page where a lecturer will select a course allocated to him for score entry. Shows a page where a lecturer will select a course allocated to him for score entry.
in a specific semester and session in a specific semester and session
""" """
current_session = Session.objects.get(is_current_session=True) current_session = Session.objects.get(is_current_session=True)
current_semester = get_object_or_404(Semester, is_current_semester=True, session=current_session) current_semester = get_object_or_404(
Semester, is_current_semester=True, session=current_session
)
# semester = Course.objects.filter(allocated_course__lecturer__pk=request.user.id, semester=current_semester) # semester = Course.objects.filter(allocated_course__lecturer__pk=request.user.id, semester=current_semester)
courses = Course.objects.filter(allocated_course__lecturer__pk=request.user.id).filter(semester=current_semester) courses = Course.objects.filter(
allocated_course__lecturer__pk=request.user.id
).filter(semester=current_semester)
context = { context = {
"current_session": current_session, "current_session": current_session,
"current_semester": current_semester, "current_semester": current_semester,
"courses": courses, "courses": courses,
} }
return render(request, 'result/add_score.html', context) return render(request, "result/add_score.html", context)
@login_required @login_required
@ -54,13 +67,16 @@ def add_score(request):
def add_score_for(request, id): def add_score_for(request, id):
""" """
Shows a page where a lecturer will add score for students that are taking courses allocated to him Shows a page where a lecturer will add score for students that are taking courses allocated to him
in a specific semester and session in a specific semester and session
""" """
current_session = Session.objects.get(is_current_session=True) current_session = Session.objects.get(is_current_session=True)
current_semester = get_object_or_404(Semester, is_current_semester=True, session=current_session) current_semester = get_object_or_404(
if request.method == 'GET': Semester, is_current_semester=True, session=current_session
courses = Course.objects.filter(allocated_course__lecturer__pk=request.user.id).filter( )
semester=current_semester) if request.method == "GET":
courses = Course.objects.filter(
allocated_course__lecturer__pk=request.user.id
).filter(semester=current_semester)
course = Course.objects.get(pk=id) course = Course.objects.get(pk=id)
# myclass = Class.objects.get(lecturer__pk=request.user.id) # myclass = Class.objects.get(lecturer__pk=request.user.id)
# myclass = get_object_or_404(Class, lecturer__pk=request.user.id) # myclass = get_object_or_404(Class, lecturer__pk=request.user.id)
@ -68,8 +84,13 @@ def add_score_for(request, id):
# students = TakenCourse.objects.filter(course__allocated_course__lecturer__pk=request.user.id).filter( # students = TakenCourse.objects.filter(course__allocated_course__lecturer__pk=request.user.id).filter(
# course__id=id).filter(student__allocated_student__lecturer__pk=request.user.id).filter( # course__id=id).filter(student__allocated_student__lecturer__pk=request.user.id).filter(
# course__semester=current_semester) # course__semester=current_semester)
students = TakenCourse.objects.filter(course__allocated_course__lecturer__pk=request.user.id).filter( students = (
course__id=id).filter(course__semester=current_semester) TakenCourse.objects.filter(
course__allocated_course__lecturer__pk=request.user.id
)
.filter(course__id=id)
.filter(course__semester=current_semester)
)
context = { context = {
"title": "Submit Score | DjangoSMS", "title": "Submit Score | DjangoSMS",
"courses": courses, "courses": courses,
@ -79,29 +100,40 @@ def add_score_for(request, id):
"current_session": current_session, "current_session": current_session,
"current_semester": current_semester, "current_semester": current_semester,
} }
return render(request, 'result/add_score_for.html', context) return render(request, "result/add_score_for.html", context)
if request.method == 'POST': if request.method == "POST":
ids = () ids = ()
data = request.POST.copy() data = request.POST.copy()
data.pop('csrfmiddlewaretoken', None) # remove csrf_token data.pop("csrfmiddlewaretoken", None) # remove csrf_token
for key in data.keys(): for key in data.keys():
ids = ids + (str(key),) # gather all the all students id (i.e the keys) in a tuple ids = ids + (
for s in range(0, len(ids)): # iterate over the list of student ids gathered above str(key),
) # gather all the all students id (i.e the keys) in a tuple
for s in range(
0, len(ids)
): # iterate over the list of student ids gathered above
student = TakenCourse.objects.get(id=ids[s]) student = TakenCourse.objects.get(id=ids[s])
# print(student) # print(student)
# print(student.student) # print(student.student)
# print(student.student.department.id) # print(student.student.department.id)
courses = Course.objects.filter(level=student.student.level).filter(program__pk=student.student.department.id).filter( courses = (
semester=current_semester) # all courses of a specific level in current semester Course.objects.filter(level=student.student.level)
.filter(program__pk=student.student.department.id)
.filter(semester=current_semester)
) # all courses of a specific level in current semester
total_credit_in_semester = 0 total_credit_in_semester = 0
for i in courses: for i in courses:
if i == courses.count(): if i == courses.count():
break break
else: else:
total_credit_in_semester += int(i.credit) total_credit_in_semester += int(i.credit)
score = data.getlist(ids[s]) # get list of score for current student in the loop score = data.getlist(
assignment = score[0] # subscript the list to get the fisrt value > ca score ids[s]
) # get list of score for current student in the loop
assignment = score[
0
] # subscript the list to get the fisrt value > ca score
mid_exam = score[1] # do the same for exam score mid_exam = score[1] # do the same for exam score
quiz = score[2] quiz = score[2]
attendance = score[3] attendance = score[3]
@ -113,7 +145,13 @@ def add_score_for(request, id):
obj.attendance = attendance # set current student attendance score obj.attendance = attendance # set current student attendance score
obj.final_exam = final_exam # set current student final_exam score obj.final_exam = final_exam # set current student final_exam score
obj.total = obj.get_total(assignment=assignment, mid_exam=mid_exam, quiz=quiz, attendance=attendance, final_exam=final_exam) obj.total = obj.get_total(
assignment=assignment,
mid_exam=mid_exam,
quiz=quiz,
attendance=attendance,
final_exam=final_exam,
)
obj.grade = obj.get_grade(total=obj.total) obj.grade = obj.get_grade(total=obj.total)
# obj.total = obj.get_total(assignment, mid_exam, quiz, attendance, final_exam) # obj.total = obj.get_total(assignment, mid_exam, quiz, attendance, final_exam)
@ -129,13 +167,23 @@ def add_score_for(request, id):
cgpa = obj.calculate_cgpa() cgpa = obj.calculate_cgpa()
try: try:
a = Result.objects.get(student=student.student, semester=current_semester, session=current_session, level=student.student.level) a = Result.objects.get(
student=student.student,
semester=current_semester,
session=current_session,
level=student.student.level,
)
a.gpa = gpa a.gpa = gpa
a.cgpa = cgpa a.cgpa = cgpa
a.save() a.save()
except: except:
Result.objects.get_or_create(student=student.student, gpa=gpa, semester=current_semester, Result.objects.get_or_create(
session=current_session, level=student.student.level) student=student.student,
gpa=gpa,
semester=current_semester,
session=current_session,
level=student.student.level,
)
# try: # try:
# a = Result.objects.get(student=student.student, semester=current_semester, level=student.student.level) # a = Result.objects.get(student=student.student, semester=current_semester, level=student.student.level)
@ -145,9 +193,11 @@ def add_score_for(request, id):
# except: # except:
# Result.objects.get_or_create(student=student.student, gpa=gpa, semester=current_semester, level=student.student.level) # Result.objects.get_or_create(student=student.student, gpa=gpa, semester=current_semester, level=student.student.level)
messages.success(request, 'Successfully Recorded! ') messages.success(request, "Successfully Recorded! ")
return HttpResponseRedirect(reverse_lazy('add_score_for', kwargs={'id': id})) return HttpResponseRedirect(reverse_lazy("add_score_for", kwargs={"id": id}))
return HttpResponseRedirect(reverse_lazy('add_score_for', kwargs={'id': id})) return HttpResponseRedirect(reverse_lazy("add_score_for", kwargs={"id": id}))
# ######################################################## # ########################################################
@ -155,7 +205,9 @@ def add_score_for(request, id):
@student_required @student_required
def grade_result(request): def grade_result(request):
student = Student.objects.get(student__pk=request.user.id) student = Student.objects.get(student__pk=request.user.id)
courses = TakenCourse.objects.filter(student__student__pk=request.user.id).filter(course__level=student.level) courses = TakenCourse.objects.filter(student__student__pk=request.user.id).filter(
course__level=student.level
)
# total_credit_in_semester = 0 # total_credit_in_semester = 0
results = Result.objects.filter(student__student__pk=request.user.id) results = Result.objects.filter(student__student__pk=request.user.id)
@ -180,7 +232,11 @@ def grade_result(request):
for i in results: for i in results:
previousLEVEL = i.level previousLEVEL = i.level
try: try:
a = Result.objects.get(student__student__pk=request.user.id, level=previousLEVEL, semester="Second") a = Result.objects.get(
student__student__pk=request.user.id,
level=previousLEVEL,
semester="Second",
)
previousCGPA = a.cgpa previousCGPA = a.cgpa
break break
except: except:
@ -191,20 +247,23 @@ def grade_result(request):
"results": results, "results": results,
"sorted_result": sorted_result, "sorted_result": sorted_result,
"student": student, "student": student,
'total_first_semester_credit': total_first_semester_credit, "total_first_semester_credit": total_first_semester_credit,
'total_sec_semester_credit': total_sec_semester_credit, "total_sec_semester_credit": total_sec_semester_credit,
'total_first_and_second_semester_credit': total_first_semester_credit + total_sec_semester_credit, "total_first_and_second_semester_credit": total_first_semester_credit
+ total_sec_semester_credit,
"previousCGPA": previousCGPA, "previousCGPA": previousCGPA,
} }
return render(request, 'result/grade_results.html', context) return render(request, "result/grade_results.html", context)
@login_required @login_required
@student_required @student_required
def assessment_result(request): def assessment_result(request):
student = Student.objects.get(student__pk=request.user.id) student = Student.objects.get(student__pk=request.user.id)
courses = TakenCourse.objects.filter(student__student__pk=request.user.id, course__level=student.level) courses = TakenCourse.objects.filter(
student__student__pk=request.user.id, course__level=student.level
)
result = Result.objects.filter(student__student__pk=request.user.id) result = Result.objects.filter(student__student__pk=request.user.id)
context = { context = {
@ -212,8 +271,8 @@ def assessment_result(request):
"result": result, "result": result,
"student": student, "student": student,
} }
return render(request, 'result/assessment_results.html', context) return render(request, "result/assessment_results.html", context)
@login_required @login_required
@ -225,14 +284,29 @@ def result_sheet_pdf_view(request, id):
course = get_object_or_404(Course, id=id) course = get_object_or_404(Course, id=id)
no_of_pass = TakenCourse.objects.filter(course__pk=id, comment="PASS").count() no_of_pass = TakenCourse.objects.filter(course__pk=id, comment="PASS").count()
no_of_fail = TakenCourse.objects.filter(course__pk=id, comment="FAIL").count() no_of_fail = TakenCourse.objects.filter(course__pk=id, comment="FAIL").count()
fname = str(current_semester) + '_semester_' + str(current_session) + '_' + str(course) + '_resultSheet.pdf' fname = (
str(current_semester)
+ "_semester_"
+ str(current_session)
+ "_"
+ str(course)
+ "_resultSheet.pdf"
)
fname = fname.replace("/", "-") fname = fname.replace("/", "-")
flocation = settings.MEDIA_ROOT + "/result_sheet/" + fname flocation = settings.MEDIA_ROOT + "/result_sheet/" + fname
doc = SimpleDocTemplate(flocation, rightMargin=0, leftMargin=6.5 * cm, topMargin=0.3 * cm, bottomMargin=0) doc = SimpleDocTemplate(
flocation,
rightMargin=0,
leftMargin=6.5 * cm,
topMargin=0.3 * cm,
bottomMargin=0,
)
styles = getSampleStyleSheet() styles = getSampleStyleSheet()
styles.add(ParagraphStyle( name="ParagraphTitle", fontSize=11, fontName="FreeSansBold")) styles.add(
Story = [Spacer(1,.2)] ParagraphStyle(name="ParagraphTitle", fontSize=11, fontName="FreeSansBold")
)
Story = [Spacer(1, 0.2)]
style = styles["Normal"] style = styles["Normal"]
# picture = request.user.picture # picture = request.user.picture
@ -250,21 +324,27 @@ def result_sheet_pdf_view(request, id):
print("\nsettings.MEDIA_ROOT", settings.MEDIA_ROOT) print("\nsettings.MEDIA_ROOT", settings.MEDIA_ROOT)
print("\nsettings.STATICFILES_DIRS[0]", settings.STATICFILES_DIRS[0]) print("\nsettings.STATICFILES_DIRS[0]", settings.STATICFILES_DIRS[0])
logo = settings.STATICFILES_DIRS[0] + "/img/logo.png" logo = settings.STATICFILES_DIRS[0] + "/img/logo.png"
im = Image(logo, 1*inch, 1*inch) im = Image(logo, 1 * inch, 1 * inch)
im.__setattr__("_offs_x", -200) im.__setattr__("_offs_x", -200)
im.__setattr__("_offs_y", -45) im.__setattr__("_offs_y", -45)
Story.append(im) Story.append(im)
style = getSampleStyleSheet() style = getSampleStyleSheet()
normal = style["Normal"] normal = style["Normal"]
normal.alignment = TA_CENTER normal.alignment = TA_CENTER
normal.fontName = "Helvetica" normal.fontName = "Helvetica"
normal.fontSize = 12 normal.fontSize = 12
normal.leading = 15 normal.leading = 15
title = "<b> "+str(current_semester) + " Semester " + str(current_session) + " Result Sheet</b>" title = (
"<b> "
+ str(current_semester)
+ " Semester "
+ str(current_session)
+ " Result Sheet</b>"
)
title = Paragraph(title.upper(), normal) title = Paragraph(title.upper(), normal)
Story.append(title) Story.append(title)
Story.append(Spacer(1,0.1*inch)) Story.append(Spacer(1, 0.1 * inch))
style = getSampleStyleSheet() style = getSampleStyleSheet()
normal = style["Normal"] normal = style["Normal"]
@ -275,7 +355,7 @@ def result_sheet_pdf_view(request, id):
title = "<b>Course lecturer: " + request.user.get_full_name + "</b>" title = "<b>Course lecturer: " + request.user.get_full_name + "</b>"
title = Paragraph(title.upper(), normal) title = Paragraph(title.upper(), normal)
Story.append(title) Story.append(title)
Story.append(Spacer(1,0.1*inch)) Story.append(Spacer(1, 0.1 * inch))
normal = style["Normal"] normal = style["Normal"]
normal.alignment = TA_CENTER normal.alignment = TA_CENTER
@ -286,46 +366,74 @@ def result_sheet_pdf_view(request, id):
title = "<b>Level: </b>" + str(level.course.level) title = "<b>Level: </b>" + str(level.course.level)
title = Paragraph(title.upper(), normal) title = Paragraph(title.upper(), normal)
Story.append(title) Story.append(title)
Story.append(Spacer(1,.6*inch)) Story.append(Spacer(1, 0.6 * inch))
elements = [] elements = []
count = 0 count = 0
header = [('S/N', 'ID NO.', 'FULL NAME', 'TOTAL', 'GRADE', 'POINT', 'COMMENT')] header = [("S/N", "ID NO.", "FULL NAME", "TOTAL", "GRADE", "POINT", "COMMENT")]
table_header = Table(header, [inch], [0.5*inch]) table_header = Table(header, [inch], [0.5 * inch])
table_header.setStyle( table_header.setStyle(
TableStyle([ TableStyle(
('BACKGROUND',(0,0),(-1,-1),colors.black), [
('TEXTCOLOR',(1,0),(-1,-1),colors.white), ("BACKGROUND", (0, 0), (-1, -1), colors.black),
('TEXTCOLOR',(0,0),(0,0),colors.cyan), ("TEXTCOLOR", (1, 0), (-1, -1), colors.white),
('ALIGN',(0,0),(-1,-1),'CENTER'), ("TEXTCOLOR", (0, 0), (0, 0), colors.cyan),
('VALIGN',(0,0),(-1,-1),'MIDDLE'), ("ALIGN", (0, 0), (-1, -1), "CENTER"),
('BOX',(0,0),(-1,-1),1,colors.black), ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
])) ("BOX", (0, 0), (-1, -1), 1, colors.black),
]
)
)
Story.append(table_header) Story.append(table_header)
for student in result: for student in result:
data = [
data = [(count+1, student.student.student.username.upper(), Paragraph(student.student.student.get_full_name.capitalize(), styles['Normal']), (
student.total, student.grade, student.point, student.comment)] count + 1,
student.student.student.username.upper(),
Paragraph(
student.student.student.get_full_name.capitalize(), styles["Normal"]
),
student.total,
student.grade,
student.point,
student.comment,
)
]
color = colors.black color = colors.black
if student.grade == 'F': if student.grade == "F":
color = colors.red color = colors.red
count += 1 count += 1
t_body = Table(data, colWidths=[inch]) t_body = Table(data, colWidths=[inch])
t_body.setStyle( t_body.setStyle(
TableStyle([ TableStyle(
('INNERGRID', (0,0), (-1,-1), 0.05, colors.black), [
('BOX', (0,0), (-1,-1), 0.1, colors.black), ("INNERGRID", (0, 0), (-1, -1), 0.05, colors.black),
])) ("BOX", (0, 0), (-1, -1), 0.1, colors.black),
]
)
)
Story.append(t_body) Story.append(t_body)
Story.append(Spacer(1,1*inch)) Story.append(Spacer(1, 1 * inch))
style_right = ParagraphStyle(name='right', parent=styles['Normal'], alignment=TA_RIGHT) style_right = ParagraphStyle(
name="right", parent=styles["Normal"], alignment=TA_RIGHT
)
tbl_data = [ tbl_data = [
[Paragraph("<b>Date:</b>_____________________________", styles["Normal"]), Paragraph("<b>No. of PASS:</b> " + str(no_of_pass), style_right)], [
[Paragraph("<b>Siganture / Stamp:</b> _____________________________", styles["Normal"]), Paragraph("<b>No. of FAIL: </b>" + str(no_of_fail), style_right)]] Paragraph("<b>Date:</b>_____________________________", styles["Normal"]),
Paragraph("<b>No. of PASS:</b> " + str(no_of_pass), style_right),
],
[
Paragraph(
"<b>Siganture / Stamp:</b> _____________________________",
styles["Normal"],
),
Paragraph("<b>No. of FAIL: </b>" + str(no_of_fail), style_right),
],
]
tbl = Table(tbl_data) tbl = Table(tbl_data)
Story.append(tbl) Story.append(tbl)
@ -333,8 +441,8 @@ def result_sheet_pdf_view(request, id):
fs = FileSystemStorage(settings.MEDIA_ROOT + "/result_sheet") fs = FileSystemStorage(settings.MEDIA_ROOT + "/result_sheet")
with fs.open(fname) as pdf: with fs.open(fname) as pdf:
response = HttpResponse(pdf, content_type='application/pdf') response = HttpResponse(pdf, content_type="application/pdf")
response['Content-Disposition'] = 'inline; filename=' + fname + '' response["Content-Disposition"] = "inline; filename=" + fname + ""
return response return response
return response return response
@ -345,16 +453,18 @@ def course_registration_form(request):
current_semester = Semester.objects.get(is_current_semester=True) current_semester = Semester.objects.get(is_current_semester=True)
current_session = Session.objects.get(is_current_session=True) current_session = Session.objects.get(is_current_session=True)
courses = TakenCourse.objects.filter(student__student__id=request.user.id) courses = TakenCourse.objects.filter(student__student__id=request.user.id)
fname = request.user.username + '.pdf' fname = request.user.username + ".pdf"
fname = fname.replace("/", "-") fname = fname.replace("/", "-")
# flocation = '/tmp/' + fname # flocation = '/tmp/' + fname
# print(MEDIA_ROOT + "\\" + fname) # print(MEDIA_ROOT + "\\" + fname)
flocation = settings.MEDIA_ROOT + "/registration_form/" + fname flocation = settings.MEDIA_ROOT + "/registration_form/" + fname
doc = SimpleDocTemplate(flocation, rightMargin=15, leftMargin=15, topMargin=0, bottomMargin=0) doc = SimpleDocTemplate(
flocation, rightMargin=15, leftMargin=15, topMargin=0, bottomMargin=0
)
styles = getSampleStyleSheet() styles = getSampleStyleSheet()
Story = [Spacer(1,0.5)] Story = [Spacer(1, 0.5)]
Story.append(Spacer(1,0.4*inch)) Story.append(Spacer(1, 0.4 * inch))
style = styles["Normal"] style = styles["Normal"]
style = getSampleStyleSheet() style = getSampleStyleSheet()
@ -363,11 +473,11 @@ def course_registration_form(request):
normal.fontName = "Helvetica" normal.fontName = "Helvetica"
normal.fontSize = 12 normal.fontSize = 12
normal.leading = 18 normal.leading = 18
title = "<b>EZOD UNIVERSITY OF TECHNOLOGY, ADAMA</b>" title = "<b>EZOD UNIVERSITY OF TECHNOLOGY, ADAMA</b>"
title = Paragraph(title.upper(), normal) title = Paragraph(title.upper(), normal)
Story.append(title) Story.append(title)
style = getSampleStyleSheet() style = getSampleStyleSheet()
school = style["Normal"] school = style["Normal"]
school.alignment = TA_CENTER school.alignment = TA_CENTER
school.fontName = "Helvetica" school.fontName = "Helvetica"
@ -378,7 +488,7 @@ def course_registration_form(request):
Story.append(school_title) Story.append(school_title)
style = getSampleStyleSheet() style = getSampleStyleSheet()
Story.append(Spacer(1,0.1*inch)) Story.append(Spacer(1, 0.1 * inch))
department = style["Normal"] department = style["Normal"]
department.alignment = TA_CENTER department.alignment = TA_CENTER
department.fontName = "Helvetica" department.fontName = "Helvetica"
@ -387,22 +497,38 @@ def course_registration_form(request):
department_title = "<b>DEPARTMENT OF COMPUTER SCIENCE & ENGINEERING</b>" department_title = "<b>DEPARTMENT OF COMPUTER SCIENCE & ENGINEERING</b>"
department_title = Paragraph(department_title, department) department_title = Paragraph(department_title, department)
Story.append(department_title) Story.append(department_title)
Story.append(Spacer(1,.3*inch)) Story.append(Spacer(1, 0.3 * inch))
title = "<b><u>STUDENT COURSE REGISTRATION FORM</u></b>" title = "<b><u>STUDENT COURSE REGISTRATION FORM</u></b>"
title = Paragraph(title.upper(), normal) title = Paragraph(title.upper(), normal)
Story.append(title) Story.append(title)
student = Student.objects.get(student__pk=request.user.id) student = Student.objects.get(student__pk=request.user.id)
style_right = ParagraphStyle(name='right', parent=styles['Normal']) style_right = ParagraphStyle(name="right", parent=styles["Normal"])
tbl_data = [ tbl_data = [
[Paragraph("<b>Registration Number : " + request.user.username.upper() + "</b>", styles["Normal"])], [
[Paragraph("<b>Name : " + request.user.get_full_name.upper() + "</b>", styles["Normal"])], Paragraph(
[Paragraph("<b>Session : " + current_session.session.upper() + "</b>", styles["Normal"]), Paragraph("<b>Level: " + student.level + "</b>", styles["Normal"]) "<b>Registration Number : " + request.user.username.upper() + "</b>",
]] styles["Normal"],
)
],
[
Paragraph(
"<b>Name : " + request.user.get_full_name.upper() + "</b>",
styles["Normal"],
)
],
[
Paragraph(
"<b>Session : " + current_session.session.upper() + "</b>",
styles["Normal"],
),
Paragraph("<b>Level: " + student.level + "</b>", styles["Normal"]),
],
]
tbl = Table(tbl_data) tbl = Table(tbl_data)
Story.append(tbl) Story.append(tbl)
Story.append(Spacer(1, 0.6*inch)) Story.append(Spacer(1, 0.6 * inch))
style = getSampleStyleSheet() style = getSampleStyleSheet()
semester = style["Normal"] semester = style["Normal"]
@ -418,44 +544,66 @@ def course_registration_form(request):
# FIRST SEMESTER # FIRST SEMESTER
count = 0 count = 0
header = [('S/No', 'Course Code', 'Course Title', 'Unit', Paragraph('Name, Siganture of course lecturer & Date', style['Normal']))] header = [
table_header = Table(header,1*[1.4*inch], 1*[0.5*inch]) (
"S/No",
"Course Code",
"Course Title",
"Unit",
Paragraph("Name, Siganture of course lecturer & Date", style["Normal"]),
)
]
table_header = Table(header, 1 * [1.4 * inch], 1 * [0.5 * inch])
table_header.setStyle( table_header.setStyle(
TableStyle([ TableStyle(
('ALIGN',(-2,-2), (-2,-2),'CENTER'), [
('VALIGN',(-2,-2), (-2,-2),'MIDDLE'), ("ALIGN", (-2, -2), (-2, -2), "CENTER"),
('ALIGN',(1,0), (1,0),'CENTER'), ("VALIGN", (-2, -2), (-2, -2), "MIDDLE"),
('VALIGN',(1,0), (1,0),'MIDDLE'), ("ALIGN", (1, 0), (1, 0), "CENTER"),
('ALIGN',(0,0), (0,0),'CENTER'), ("VALIGN", (1, 0), (1, 0), "MIDDLE"),
('VALIGN',(0,0), (0,0),'MIDDLE'), ("ALIGN", (0, 0), (0, 0), "CENTER"),
('ALIGN',(-4,0), (-4,0),'LEFT'), ("VALIGN", (0, 0), (0, 0), "MIDDLE"),
('VALIGN',(-4,0), (-4,0),'MIDDLE'), ("ALIGN", (-4, 0), (-4, 0), "LEFT"),
('ALIGN',(-3,0), (-3,0),'LEFT'), ("VALIGN", (-4, 0), (-4, 0), "MIDDLE"),
('VALIGN',(-3,0), (-3,0),'MIDDLE'), ("ALIGN", (-3, 0), (-3, 0), "LEFT"),
('TEXTCOLOR',(0,-1),(-1,-1),colors.black), ("VALIGN", (-3, 0), (-3, 0), "MIDDLE"),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), ("TEXTCOLOR", (0, -1), (-1, -1), colors.black),
('BOX', (0,0), (-1,-1), 0.25, colors.black), ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black),
])) ("BOX", (0, 0), (-1, -1), 0.25, colors.black),
]
)
)
Story.append(table_header) Story.append(table_header)
first_semester_unit = 0 first_semester_unit = 0
for course in courses: for course in courses:
if course.course.semester == FIRST: if course.course.semester == FIRST:
first_semester_unit += int(course.course.credit) first_semester_unit += int(course.course.credit)
data = [(count+1, course.course.code.upper(), Paragraph(course.course.title, style['Normal']), course.course.credit, '')] data = [
(
count + 1,
course.course.code.upper(),
Paragraph(course.course.title, style["Normal"]),
course.course.credit,
"",
)
]
color = colors.black color = colors.black
count += 1 count += 1
table_body=Table(data,1*[1.4*inch], 1*[0.3*inch]) table_body = Table(data, 1 * [1.4 * inch], 1 * [0.3 * inch])
table_body.setStyle( table_body.setStyle(
TableStyle([ TableStyle(
('ALIGN',(-2,-2), (-2,-2),'CENTER'), [
('ALIGN',(1,0), (1,0),'CENTER'), ("ALIGN", (-2, -2), (-2, -2), "CENTER"),
('ALIGN',(0,0), (0,0),'CENTER'), ("ALIGN", (1, 0), (1, 0), "CENTER"),
('ALIGN',(-4,0), (-4,0),'LEFT'), ("ALIGN", (0, 0), (0, 0), "CENTER"),
('TEXTCOLOR',(0,-1),(-1,-1),colors.black), ("ALIGN", (-4, 0), (-4, 0), "LEFT"),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), ("TEXTCOLOR", (0, -1), (-1, -1), colors.black),
('BOX', (0,0), (-1,-1), 0.25, colors.black), ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black),
])) ("BOX", (0, 0), (-1, -1), 0.25, colors.black),
]
)
)
Story.append(table_body) Story.append(table_body)
style = getSampleStyleSheet() style = getSampleStyleSheet()
@ -464,12 +612,14 @@ def course_registration_form(request):
semester.fontName = "Helvetica" semester.fontName = "Helvetica"
semester.fontSize = 8 semester.fontSize = 8
semester.leading = 18 semester.leading = 18
semester_title = "<b>Total Second First Credit : " + str(first_semester_unit) + "</b>" semester_title = (
"<b>Total Second First Credit : " + str(first_semester_unit) + "</b>"
)
semester_title = Paragraph(semester_title, semester) semester_title = Paragraph(semester_title, semester)
Story.append(semester_title) Story.append(semester_title)
# FIRST SEMESTER ENDS HERE # FIRST SEMESTER ENDS HERE
Story.append(Spacer(1, 0.6*inch)) Story.append(Spacer(1, 0.6 * inch))
style = getSampleStyleSheet() style = getSampleStyleSheet()
semester = style["Normal"] semester = style["Normal"]
@ -482,44 +632,68 @@ def course_registration_form(request):
Story.append(semester_title) Story.append(semester_title)
# SECOND SEMESTER # SECOND SEMESTER
count = 0 count = 0
header = [('S/No', 'Course Code', 'Course Title', 'Unit', Paragraph('<b>Name, Signature of course lecturer & Date</b>', style['Normal']))] header = [
table_header = Table(header,1*[1.4*inch], 1*[0.5*inch]) (
"S/No",
"Course Code",
"Course Title",
"Unit",
Paragraph(
"<b>Name, Signature of course lecturer & Date</b>", style["Normal"]
),
)
]
table_header = Table(header, 1 * [1.4 * inch], 1 * [0.5 * inch])
table_header.setStyle( table_header.setStyle(
TableStyle([ TableStyle(
('ALIGN',(-2,-2), (-2,-2),'CENTER'), [
('VALIGN',(-2,-2), (-2,-2),'MIDDLE'), ("ALIGN", (-2, -2), (-2, -2), "CENTER"),
('ALIGN',(1,0), (1,0),'CENTER'), ("VALIGN", (-2, -2), (-2, -2), "MIDDLE"),
('VALIGN',(1,0), (1,0),'MIDDLE'), ("ALIGN", (1, 0), (1, 0), "CENTER"),
('ALIGN',(0,0), (0,0),'CENTER'), ("VALIGN", (1, 0), (1, 0), "MIDDLE"),
('VALIGN',(0,0), (0,0),'MIDDLE'), ("ALIGN", (0, 0), (0, 0), "CENTER"),
('ALIGN',(-4,0), (-4,0),'LEFT'), ("VALIGN", (0, 0), (0, 0), "MIDDLE"),
('VALIGN',(-4,0), (-4,0),'MIDDLE'), ("ALIGN", (-4, 0), (-4, 0), "LEFT"),
('ALIGN',(-3,0), (-3,0),'LEFT'), ("VALIGN", (-4, 0), (-4, 0), "MIDDLE"),
('VALIGN',(-3,0), (-3,0),'MIDDLE'), ("ALIGN", (-3, 0), (-3, 0), "LEFT"),
('TEXTCOLOR',(0,-1),(-1,-1),colors.black), ("VALIGN", (-3, 0), (-3, 0), "MIDDLE"),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), ("TEXTCOLOR", (0, -1), (-1, -1), colors.black),
('BOX', (0,0), (-1,-1), 0.25, colors.black), ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black),
])) ("BOX", (0, 0), (-1, -1), 0.25, colors.black),
]
)
)
Story.append(table_header) Story.append(table_header)
second_semester_unit = 0 second_semester_unit = 0
for course in courses: for course in courses:
if course.course.semester == SECOND: if course.course.semester == SECOND:
second_semester_unit += int(course.course.credit) second_semester_unit += int(course.course.credit)
data = [(count+1, course.course.code.upper(), Paragraph(course.course.title, style['Normal']), course.course.credit, '')] data = [
(
count + 1,
course.course.code.upper(),
Paragraph(course.course.title, style["Normal"]),
course.course.credit,
"",
)
]
color = colors.black color = colors.black
count += 1 count += 1
table_body=Table(data,1*[1.4*inch], 1*[0.3*inch]) table_body = Table(data, 1 * [1.4 * inch], 1 * [0.3 * inch])
table_body.setStyle( table_body.setStyle(
TableStyle([ TableStyle(
('ALIGN',(-2,-2), (-2,-2),'CENTER'), [
('ALIGN',(1,0), (1,0),'CENTER'), ("ALIGN", (-2, -2), (-2, -2), "CENTER"),
('ALIGN',(0,0), (0,0),'CENTER'), ("ALIGN", (1, 0), (1, 0), "CENTER"),
('ALIGN',(-4,0), (-4,0),'LEFT'), ("ALIGN", (0, 0), (0, 0), "CENTER"),
('TEXTCOLOR',(0,-1),(-1,-1),colors.black), ("ALIGN", (-4, 0), (-4, 0), "LEFT"),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), ("TEXTCOLOR", (0, -1), (-1, -1), colors.black),
('BOX', (0,0), (-1,-1), 0.25, colors.black), ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black),
])) ("BOX", (0, 0), (-1, -1), 0.25, colors.black),
]
)
)
Story.append(table_body) Story.append(table_body)
style = getSampleStyleSheet() style = getSampleStyleSheet()
@ -528,7 +702,9 @@ def course_registration_form(request):
semester.fontName = "Helvetica" semester.fontName = "Helvetica"
semester.fontSize = 8 semester.fontSize = 8
semester.leading = 18 semester.leading = 18
semester_title = "<b>Total Second Semester Credit : " + str(second_semester_unit) + "</b>" semester_title = (
"<b>Total Second Semester Credit : " + str(second_semester_unit) + "</b>"
)
semester_title = Paragraph(semester_title, semester) semester_title = Paragraph(semester_title, semester)
Story.append(semester_title) Story.append(semester_title)
@ -540,22 +716,28 @@ def course_registration_form(request):
certification.fontSize = 8 certification.fontSize = 8
certification.leading = 18 certification.leading = 18
student = Student.objects.get(student__pk=request.user.id) student = Student.objects.get(student__pk=request.user.id)
certification_text = "CERTIFICATION OF REGISTRATION: I certify that <b>" + str(request.user.get_full_name.upper()) + "</b>\ certification_text = (
has been duly registered for the <b>" + student.level + " level </b> of study in the department\ "CERTIFICATION OF REGISTRATION: I certify that <b>"
+ str(request.user.get_full_name.upper())
+ "</b>\
has been duly registered for the <b>"
+ student.level
+ " level </b> of study in the department\
of COMPUTER SICENCE & ENGINEERING and that the courses and credits registered are as approved by the senate of the University" of COMPUTER SICENCE & ENGINEERING and that the courses and credits registered are as approved by the senate of the University"
)
certification_text = Paragraph(certification_text, certification) certification_text = Paragraph(certification_text, certification)
Story.append(certification_text) Story.append(certification_text)
# FIRST SEMESTER ENDS HERE # FIRST SEMESTER ENDS HERE
logo = settings.STATICFILES_DIRS[0] + "/img/logo.png" logo = settings.STATICFILES_DIRS[0] + "/img/logo.png"
im_logo = Image(logo, 1*inch, 1*inch) im_logo = Image(logo, 1 * inch, 1 * inch)
im_logo.__setattr__("_offs_x", -218) im_logo.__setattr__("_offs_x", -218)
im_logo.__setattr__("_offs_y", 480) im_logo.__setattr__("_offs_y", 480)
Story.append(im_logo) Story.append(im_logo)
picture = settings.BASE_DIR + request.user.get_picture() picture = settings.BASE_DIR + request.user.get_picture()
im = Image(picture, 1.0*inch, 1.0*inch) im = Image(picture, 1.0 * inch, 1.0 * inch)
im.__setattr__("_offs_x", 218) im.__setattr__("_offs_x", 218)
im.__setattr__("_offs_y", 550) im.__setattr__("_offs_y", 550)
Story.append(im) Story.append(im)
@ -563,7 +745,7 @@ def course_registration_form(request):
doc.build(Story) doc.build(Story)
fs = FileSystemStorage(settings.MEDIA_ROOT + "/registration_form") fs = FileSystemStorage(settings.MEDIA_ROOT + "/registration_form")
with fs.open(fname) as pdf: with fs.open(fname) as pdf:
response = HttpResponse(pdf, content_type='application/pdf') response = HttpResponse(pdf, content_type="application/pdf")
response['Content-Disposition'] = 'inline; filename='+fname+'' response["Content-Disposition"] = "inline; filename=" + fname + ""
return response return response
return response return response

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class SearchConfig(AppConfig): class SearchConfig(AppConfig):
name = 'search' name = "search"

View File

@ -2,5 +2,5 @@ from django.urls import path
from .views import SearchView from .views import SearchView
urlpatterns = [ urlpatterns = [
path('', SearchView.as_view(), name='query'), path("", SearchView.as_view(), name="query"),
] ]

View File

@ -27,14 +27,6 @@
# ''' # '''
# search.views.py # search.views.py
from itertools import chain from itertools import chain
from django.views.generic import ListView from django.views.generic import ListView
@ -48,36 +40,31 @@ from quiz.models import Quiz
class SearchView(ListView): class SearchView(ListView):
template_name = 'search/search_view.html' template_name = "search/search_view.html"
paginate_by = 20 paginate_by = 20
count = 0 count = 0
def get_context_data(self, *args, **kwargs): def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs) context = super().get_context_data(*args, **kwargs)
context['count'] = self.count or 0 context["count"] = self.count or 0
context['query'] = self.request.GET.get('q') context["query"] = self.request.GET.get("q")
return context return context
def get_queryset(self): def get_queryset(self):
request = self.request request = self.request
query = request.GET.get('q', None) query = request.GET.get("q", None)
if query is not None: if query is not None:
news_events_results = NewsAndEvents.objects.search(query) news_events_results = NewsAndEvents.objects.search(query)
program_results = Program.objects.search(query) program_results = Program.objects.search(query)
course_results = Course.objects.search(query) course_results = Course.objects.search(query)
quiz_results = Quiz.objects.search(query) quiz_results = Quiz.objects.search(query)
# combine querysets # combine querysets
queryset_chain = chain( queryset_chain = chain(
news_events_results, news_events_results, program_results, course_results, quiz_results
program_results, )
course_results, qs = sorted(queryset_chain, key=lambda instance: instance.pk, reverse=True)
quiz_results self.count = len(qs) # since qs is actually a list
)
qs = sorted(queryset_chain,
key=lambda instance: instance.pk,
reverse=True)
self.count = len(qs) # since qs is actually a list
return qs return qs
return NewsAndEvents.objects.none() # just an empty queryset as default return NewsAndEvents.objects.none() # just an empty queryset as default