Started on createAssignment and createClass

This commit is contained in:
Rushil Umaretiya 2020-06-16 16:28:17 -04:00
parent cbd3ddb4e7
commit 2d58262a8d
10 changed files with 177 additions and 26 deletions

View File

@ -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)

View File

@ -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']

View File

@ -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 %}

View File

@ -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>

View 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 %}

View File

@ -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 %}

View File

@ -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">

View File

@ -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">

View File

@ -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"),
] ]

View File

@ -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