mirror of
https://github.com/Rushilwiz/SkoolOS.git
synced 2025-04-16 02:10:19 -04:00
Started on createAssignment and createClass
This commit is contained in:
parent
cbd3ddb4e7
commit
2d58262a8d
|
@ -18,31 +18,32 @@ class Student(models.Model):
|
||||||
super(Student, self).save(*args, **kwargs)
|
super(Student, self).save(*args, **kwargs)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.user.username}'s Profile"
|
return f"{self.user.first_name} {self.user.last_name} ({self.user.username})"
|
||||||
|
|
||||||
|
|
||||||
class Assignment(models.Model):
|
class Assignment(models.Model):
|
||||||
owner = models.ForeignKey(User, null=True, blank=True, related_name='aowner', on_delete=models.CASCADE)
|
owner = models.ForeignKey(User, null=True, blank=True, related_name='aowner', on_delete=models.CASCADE)
|
||||||
|
|
||||||
name=models.CharField(max_length=100, primary_key=True)
|
name=models.CharField(max_length=100, primary_key=True)
|
||||||
due_date=models.DateTimeField()
|
due_date=models.DateTimeField()
|
||||||
# files = models.ManyToManyField(DefFiles)
|
# files = models.ManyToManyField(DefFiles)
|
||||||
files=models.CharField(max_length=100, default="", blank=True)
|
files=models.CharField(max_length=100, default="", blank=True)
|
||||||
path=models.CharField(max_length=100)
|
path=models.CharField(max_length=100, default="", blank=True)
|
||||||
classes=models.CharField(max_length=100)
|
classes=models.CharField(max_length=100, default="", blank=True)
|
||||||
teacher=models.CharField(max_length=100)
|
teacher=models.CharField(max_length=100, default="", blank=True)
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '%s' % (self.name)
|
return f'{self.name}'
|
||||||
|
|
||||||
|
|
||||||
class Class(models.Model):
|
class Class(models.Model):
|
||||||
owner = models.ForeignKey(User, null=True, blank=True, related_name='cowner', on_delete=models.CASCADE)
|
owner = models.ForeignKey(User, null=True, blank=True, related_name='cowner', on_delete=models.CASCADE)
|
||||||
teacher = models.CharField(max_length=100)
|
teacher = models.CharField(max_length=100, blank=True)
|
||||||
|
subject = models.CharField(max_length=50, blank=True)
|
||||||
|
period = models.PositiveIntegerField(null=True, blank=True, default=0)
|
||||||
name = models.CharField(primary_key=True, max_length=100)
|
name = models.CharField(primary_key=True, max_length=100)
|
||||||
id = models.CharField(max_length=8, blank=True, null=True)
|
id = models.CharField(max_length=8, blank=True, null=True)
|
||||||
description = models.CharField(default="Class Description", max_length=500)
|
description = models.CharField(default="Class Description", max_length=500, blank=True)
|
||||||
repo=models.URLField(default="", blank=True)
|
repo=models.URLField(default="", blank=True)
|
||||||
path=models.CharField(max_length=100, default="")
|
path=models.CharField(max_length=100, default="", blank=True)
|
||||||
assignments=models.ManyToManyField(Assignment, blank=True)
|
assignments=models.ManyToManyField(Assignment, blank=True)
|
||||||
default_file=models.CharField(max_length=100, default="", blank=True)
|
default_file=models.CharField(max_length=100, default="", blank=True)
|
||||||
confirmed=models.ManyToManyField(Student, blank=True, related_name='confirmed')
|
confirmed=models.ManyToManyField(Student, blank=True, related_name='confirmed')
|
||||||
|
@ -60,7 +61,7 @@ class Class(models.Model):
|
||||||
return super(Class, self).save(*args, **kwargs)
|
return super(Class, self).save(*args, **kwargs)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return f"{self.user.first_name} {self.user.last_name} ({self.user.username})"
|
||||||
|
|
||||||
class Teacher(models.Model):
|
class Teacher(models.Model):
|
||||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from api.models import Student, Teacher
|
from api.models import Student, Teacher, Class, Assignment
|
||||||
import re
|
import re
|
||||||
|
|
||||||
class UserUpdateForm(forms.ModelForm):
|
class UserUpdateForm(forms.ModelForm):
|
||||||
|
@ -26,3 +26,54 @@ class TeacherUpdateForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Teacher
|
model = Teacher
|
||||||
fields = ['git']
|
fields = ['git']
|
||||||
|
|
||||||
|
class ClassCreationForm (forms.ModelForm):
|
||||||
|
subject = forms.CharField(max_length=50)
|
||||||
|
period = forms.IntegerField(min_value=0, max_value=9)
|
||||||
|
description = forms.CharField(widget=forms.Textarea)
|
||||||
|
unconfirmed = forms.ModelMultipleChoiceField(queryset=Student.objects.all(), label="Invite students")
|
||||||
|
|
||||||
|
|
||||||
|
def clean_period(self):
|
||||||
|
pd = self.cleaned_data['period']
|
||||||
|
if pd < 1 or pd > 9:
|
||||||
|
raise forms.ValidationError("Invalid period")
|
||||||
|
return pd;
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ClassCreationForm, self).__init__(*args, **kwargs)
|
||||||
|
self.fields['period'].widget.attrs['min'] = 0
|
||||||
|
# Only in case we build the form from an instance
|
||||||
|
# (otherwise, 'unconfirmed' list should be empty)
|
||||||
|
if kwargs.get('instance'):
|
||||||
|
# We get the 'initial' keyword argument or initialize it
|
||||||
|
# as a dict if it didn't exist.
|
||||||
|
initial = kwargs.setdefault('initial', {})
|
||||||
|
# The widget for a ModelMultipleChoiceField expects
|
||||||
|
# a list of primary key for the selected data.
|
||||||
|
initial['unconfirmed'] = [t.pk for t in kwargs['instance'].unconfirmed.all()]
|
||||||
|
|
||||||
|
# Overriding save allows us to process the value of 'unconfirmed' field
|
||||||
|
def save(self, commit=True):
|
||||||
|
# Get the unsave Pizza instance
|
||||||
|
instance = forms.ModelForm.save(self, False)
|
||||||
|
|
||||||
|
# Prepare a 'save_m2m' method for the form,
|
||||||
|
old_save_m2m = self.save_m2m
|
||||||
|
def save_m2m():
|
||||||
|
old_save_m2m()
|
||||||
|
# This is where we actually link the pizza with toppings
|
||||||
|
instance.topping_set.clear()
|
||||||
|
instance.topping_set.add(*self.cleaned_data['unconfirmed'])
|
||||||
|
self.save_m2m = save_m2m
|
||||||
|
|
||||||
|
# Do we need to save all changes now?
|
||||||
|
if commit:
|
||||||
|
instance.save()
|
||||||
|
self.save_m2m()
|
||||||
|
|
||||||
|
return instance
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Class
|
||||||
|
fields = ['subject', 'period', 'description', 'unconfirmed']
|
||||||
|
|
|
@ -34,6 +34,12 @@
|
||||||
<!-- Navbar Right Side -->
|
<!-- Navbar Right Side -->
|
||||||
<div class="navbar-nav">
|
<div class="navbar-nav">
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
|
{% if isTeacher %}
|
||||||
|
<a class="nav-item nav-link" href="{% url 'create-assignment' %}">Create Assignment</a>
|
||||||
|
<a class="nav-item nav-link" href="{% url 'create-class' %}">Create Class</a>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
<a class="nav-item nav-link" href="{% url 'profile' %}">{{ user.username }}</a>
|
<a class="nav-item nav-link" href="{% url 'profile' %}">{{ user.username }}</a>
|
||||||
<a class="nav-item nav-link" href="{% url 'logout' %}">Logout</a>
|
<a class="nav-item nav-link" href="{% url 'logout' %}">Logout</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -11,6 +11,12 @@
|
||||||
<small class="text-muted">Due: {{ assignment.due_date|date:"F d, Y" }}</small>
|
<small class="text-muted">Due: {{ assignment.due_date|date:"F d, Y" }}</small>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
{% empty %}
|
||||||
|
{% if isTeacher %}
|
||||||
|
<p class="mr-2">Looks like you haven't made any assignments yet, hit the button in the top right to get started</p>
|
||||||
|
{% else %}
|
||||||
|
<p class="mr-2">Looks like there aren't any assignments at the moment, you got lucky this time!</p>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -20,6 +26,8 @@
|
||||||
<ul>
|
<ul>
|
||||||
{% for teacher in teachers %}
|
{% for teacher in teachers %}
|
||||||
<li>{{ teacher.user.first_name }} {{ teacher.user.last_name }} ({{teacher.ion_user}})</li>
|
<li>{{ teacher.user.first_name }} {{ teacher.user.last_name }} ({{teacher.ion_user}})</li>
|
||||||
|
{% empty %}
|
||||||
|
<li>No Teachers, weird...</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
26
Website/skoolos/templates/skoolos/createClass.html
Normal file
26
Website/skoolos/templates/skoolos/createClass.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{% extends "skoolos/base.html" %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
{% block content %}
|
||||||
|
<legend class="border-bottom mb-4">Classes</legend>
|
||||||
|
<ul>
|
||||||
|
{% for class in classes %}
|
||||||
|
<li>{{ class.name }}</li>
|
||||||
|
{% empty %}
|
||||||
|
<li>Not teaching any classes</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
<fieldset class="form-group">
|
||||||
|
<legend class="border-bottom mb-4"> Create a new class </legend>
|
||||||
|
{{ classForm|crispy }}
|
||||||
|
<!-- mmmm crispy yummm -->
|
||||||
|
<small class="text-secondary">Use ctrl to select multiple students</small>
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="btn btn-outline-info">Create</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
|
@ -10,6 +10,12 @@
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
{% empty %}
|
||||||
|
{% if isTeacher %}
|
||||||
|
<p>Looks like you haven't created any classes yet, hit the button in the top right to get started.</p>
|
||||||
|
{% else %}
|
||||||
|
<p>Looks like you're not enrolled in any classes at the moment! Ask your teacher if you think this is wrong.</p>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<div class="media">
|
<div class="media">
|
||||||
<div class="media-body">
|
<div class="media-body">
|
||||||
<h2 class="account-heading">{{ user.username }}</h2>
|
<h2 class="account-heading">{{ user.username }}</h2>
|
||||||
|
<p class="text-secondary">Student</p>
|
||||||
<large>{{ user.first_name }} {{ user.last_name }}</large>
|
<large>{{ user.first_name }} {{ user.last_name }}</large>
|
||||||
<p class="text-secondary">
|
<p class="text-secondary">
|
||||||
{{ user.email }}
|
{{ user.email }}
|
||||||
|
@ -16,6 +17,8 @@
|
||||||
<ul>
|
<ul>
|
||||||
{% for class in classes %}
|
{% for class in classes %}
|
||||||
<li>{{ class.name }}</li>
|
<li>{{ class.name }}</li>
|
||||||
|
{% empty %}
|
||||||
|
<li>No classes</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
<form method="post" enctype="multipart/form-data">
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<div class="media">
|
<div class="media">
|
||||||
<div class="media-body">
|
<div class="media-body">
|
||||||
<h2 class="account-heading">{{ user.username }}</h2>
|
<h2 class="account-heading">{{ user.username }}</h2>
|
||||||
|
<p class="text-secondary">Teacher</p>
|
||||||
<large>{{ user.first_name }} {{ user.last_name }}</large>
|
<large>{{ user.first_name }} {{ user.last_name }}</large>
|
||||||
<p class="text-secondary">
|
<p class="text-secondary">
|
||||||
{{ user.email }}
|
{{ user.email }}
|
||||||
|
@ -16,6 +17,8 @@
|
||||||
<ul>
|
<ul>
|
||||||
{% for class in classes %}
|
{% for class in classes %}
|
||||||
<li>{{ class.name }}</li>
|
<li>{{ class.name }}</li>
|
||||||
|
{% empty %}
|
||||||
|
<li>Not teaching any classes</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
<form method="post" enctype="multipart/form-data">
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
|
|
@ -7,4 +7,6 @@ urlpatterns = [
|
||||||
path('', views.home, name='home'),
|
path('', views.home, name='home'),
|
||||||
path('profile/', views.profile, name='profile'),
|
path('profile/', views.profile, name='profile'),
|
||||||
path("class/<str:id>", views.classDetail, name="class"),
|
path("class/<str:id>", views.classDetail, name="class"),
|
||||||
|
path("create-class/", views.createClass, name="create-class"),
|
||||||
|
path("create-assignment/", views.createAssignment, name="create-assignment"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,7 +5,12 @@ from django.contrib import messages
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
from .forms import UserUpdateForm, StudentUpdateForm, TeacherUpdateForm
|
from .forms import (
|
||||||
|
UserUpdateForm,
|
||||||
|
StudentUpdateForm,
|
||||||
|
TeacherUpdateForm,
|
||||||
|
ClassCreationForm,
|
||||||
|
)
|
||||||
|
|
||||||
from api.models import Student, Teacher, Class, Assignment
|
from api.models import Student, Teacher, Class, Assignment
|
||||||
|
|
||||||
|
@ -14,14 +19,14 @@ from api.models import Student, Teacher, Class, Assignment
|
||||||
@login_required()
|
@login_required()
|
||||||
def home (request):
|
def home (request):
|
||||||
try:
|
try:
|
||||||
student = Student.objects.get(user=request.user)
|
student = request.user.student
|
||||||
return render(request, "skoolos/home.html", {'classes': student.confirmed.all()})
|
return render(request, "skoolos/home.html", {'classes': student.confirmed.all(), 'isTeacher': False})
|
||||||
except Student.DoesNotExist:
|
except Student.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
teacher = Teacher.objects.get(user=request.user)
|
teacher = request.user.teacher
|
||||||
return render(request, "skoolos/home.html", {'classes': teacher.classes.all()})
|
return render(request, "skoolos/home.html", {'classes': teacher.classes.all(), 'isTeacher': True})
|
||||||
except Teacher.DoesNotExist:
|
except Teacher.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -36,38 +41,37 @@ def classDetail (request, id):
|
||||||
classObj = Class.objects.get(id=id)
|
classObj = Class.objects.get(id=id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
student = Student.objects.get(user=request.user)
|
student = request.user.student
|
||||||
except Student.DoesNotExist:
|
except Student.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if classObj.confirmed.filter(user=student.user).count() != 1:
|
if classObj.confirmed.filter(user=student.user).count() != 1:
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
else:
|
else:
|
||||||
return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all()})
|
return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all(), 'isTeacher': False})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
teacher = Teacher.objects.get(user=request.user)
|
teacher = request.user.teacher
|
||||||
return render(request, "skoolos/home.html", {'classes': teacher.classes.all()})
|
|
||||||
except Teacher.DoesNotExist:
|
except Teacher.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if classObj.confirmed.filter(user=student.user).count() != 1:
|
if teacher.classes.filter(id=classObj.id).count() != 1:
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
else:
|
else:
|
||||||
return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all()})
|
return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all(), 'isTeacher': True})
|
||||||
|
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
|
|
||||||
@login_required()
|
@login_required()
|
||||||
def profile (request):
|
def profile (request):
|
||||||
try:
|
try:
|
||||||
student = Student.objects.get(user=request.user)
|
student = request.user.student
|
||||||
return student_profile(request)
|
return student_profile(request)
|
||||||
except Student.DoesNotExist:
|
except Student.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
teacher = Teacher.objects.get(user=request.user)
|
teacher = request.user.teacher
|
||||||
return teacher_profile(request)
|
return teacher_profile(request)
|
||||||
except Teacher.DoesNotExist:
|
except Teacher.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
@ -91,7 +95,8 @@ def student_profile (request):
|
||||||
context = {
|
context = {
|
||||||
'userForm': userForm,
|
'userForm': userForm,
|
||||||
'profileForm': profileForm,
|
'profileForm': profileForm,
|
||||||
'classes': request.user.student.confirmed.all()
|
'classes': request.user.student.confirmed.all(),
|
||||||
|
'isTeacher': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(request, 'skoolos/profile_student.html', context)
|
return render(request, 'skoolos/profile_student.html', context)
|
||||||
|
@ -113,7 +118,47 @@ def teacher_profile (request):
|
||||||
context = {
|
context = {
|
||||||
'userForm': userForm,
|
'userForm': userForm,
|
||||||
'profileForm': profileForm,
|
'profileForm': profileForm,
|
||||||
'classes': request.user.teacher.classes.all()
|
'classes': request.user.teacher.classes.all(),
|
||||||
|
'isTeacher': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(request, 'skoolos/profile_teacher.html', context)
|
return render(request, 'skoolos/profile_teacher.html', context)
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def createClass (request):
|
||||||
|
try:
|
||||||
|
teacher = request.user.teacher
|
||||||
|
except Teacher.DoesNotExist:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
return createClassHelper(request)
|
||||||
|
|
||||||
|
return redirect('/')
|
||||||
|
|
||||||
|
def createClassHelper(request):
|
||||||
|
teacher = request.user.teacher
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
userForm = UserUpdateForm(request.POST, instance=request.user)
|
||||||
|
profileForm = TeacherUpdateForm(request.POST,
|
||||||
|
instance=request.user.teacher)
|
||||||
|
if userForm.is_valid() and profileForm.is_valid():
|
||||||
|
userForm.save()
|
||||||
|
profileForm.save()
|
||||||
|
messages.success(request, "Your account has been updated!")
|
||||||
|
return redirect('profile')
|
||||||
|
else:
|
||||||
|
classForm = ClassCreationForm()
|
||||||
|
|
||||||
|
context = {
|
||||||
|
'teacher': teacher,
|
||||||
|
'classes': teacher.classes.all(),
|
||||||
|
'classForm': classForm
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return render(request, "skoolos/createClass.html", context)
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def createAssignment (request):
|
||||||
|
pass
|
||||||
|
|
Loading…
Reference in New Issue
Block a user