codeforlife-portal 8.0.0__py2.py3-none-any.whl → 8.0.2__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of codeforlife-portal might be problematic. Click here for more details.
- cfl_common/common/models.py +20 -43
- {codeforlife_portal-8.0.0.dist-info → codeforlife_portal-8.0.2.dist-info}/METADATA +1 -1
- {codeforlife_portal-8.0.0.dist-info → codeforlife_portal-8.0.2.dist-info}/RECORD +11 -11
- {codeforlife_portal-8.0.0.dist-info → codeforlife_portal-8.0.2.dist-info}/WHEEL +1 -1
- portal/__init__.py +1 -1
- portal/forms/teach.py +57 -152
- portal/templates/portal/teach/teacher_edit_class.html +18 -8
- portal/tests/test_class.py +244 -229
- portal/views/teacher/teach.py +17 -8
- {codeforlife_portal-8.0.0.dist-info → codeforlife_portal-8.0.2.dist-info}/LICENSE.md +0 -0
- {codeforlife_portal-8.0.0.dist-info → codeforlife_portal-8.0.2.dist-info}/top_level.txt +0 -0
cfl_common/common/models.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import re
|
|
2
|
+
import typing as t
|
|
2
3
|
from datetime import timedelta
|
|
3
4
|
from uuid import uuid4
|
|
4
5
|
|
|
@@ -7,6 +8,10 @@ from django.db import models
|
|
|
7
8
|
from django.utils import timezone
|
|
8
9
|
from django_countries.fields import CountryField
|
|
9
10
|
|
|
11
|
+
if t.TYPE_CHECKING:
|
|
12
|
+
from django.db.models import ManyToManyField
|
|
13
|
+
from game.models import Worksheet
|
|
14
|
+
|
|
10
15
|
|
|
11
16
|
class UserProfile(models.Model):
|
|
12
17
|
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
|
@@ -43,9 +48,7 @@ class SchoolModelManager(models.Manager):
|
|
|
43
48
|
|
|
44
49
|
class School(models.Model):
|
|
45
50
|
name = models.CharField(max_length=200, unique=True)
|
|
46
|
-
country = CountryField(
|
|
47
|
-
blank_label="(select country)", null=True, blank=True
|
|
48
|
-
)
|
|
51
|
+
country = CountryField(blank_label="(select country)", null=True, blank=True)
|
|
49
52
|
# TODO: Create an Address model to house address details
|
|
50
53
|
county = models.CharField(max_length=50, blank=True, null=True)
|
|
51
54
|
creation_time = models.DateTimeField(default=timezone.now, null=True)
|
|
@@ -68,11 +71,7 @@ class School(models.Model):
|
|
|
68
71
|
|
|
69
72
|
def admins(self):
|
|
70
73
|
teachers = self.teacher_school.all()
|
|
71
|
-
return
|
|
72
|
-
[teacher for teacher in teachers if teacher.is_admin]
|
|
73
|
-
if teachers
|
|
74
|
-
else None
|
|
75
|
-
)
|
|
74
|
+
return [teacher for teacher in teachers if teacher.is_admin] if teachers else None
|
|
76
75
|
|
|
77
76
|
def anonymise(self):
|
|
78
77
|
self.name = uuid4().hex
|
|
@@ -130,10 +129,7 @@ class Teacher(models.Model):
|
|
|
130
129
|
def teaches(self, userprofile):
|
|
131
130
|
if hasattr(userprofile, "student"):
|
|
132
131
|
student = userprofile.student
|
|
133
|
-
return (
|
|
134
|
-
not student.is_independent()
|
|
135
|
-
and student.class_field.teacher == self
|
|
136
|
-
)
|
|
132
|
+
return not student.is_independent() and student.class_field.teacher == self
|
|
137
133
|
|
|
138
134
|
def has_school(self):
|
|
139
135
|
return self.school is not (None or "")
|
|
@@ -165,14 +161,10 @@ class SchoolTeacherInvitation(models.Model):
|
|
|
165
161
|
null=True,
|
|
166
162
|
on_delete=models.SET_NULL,
|
|
167
163
|
)
|
|
168
|
-
invited_teacher_first_name = models.CharField(
|
|
169
|
-
max_length=150
|
|
170
|
-
) # Same as User model
|
|
164
|
+
invited_teacher_first_name = models.CharField(max_length=150) # Same as User model
|
|
171
165
|
# TODO: Make not nullable once data has been transferred
|
|
172
166
|
_invited_teacher_first_name = models.BinaryField(null=True, blank=True)
|
|
173
|
-
invited_teacher_last_name = models.CharField(
|
|
174
|
-
max_length=150
|
|
175
|
-
) # Same as User model
|
|
167
|
+
invited_teacher_last_name = models.CharField(max_length=150) # Same as User model
|
|
176
168
|
# TODO: Make not nullable once data has been transferred
|
|
177
169
|
_invited_teacher_last_name = models.BinaryField(null=True, blank=True)
|
|
178
170
|
# TODO: Switch to a CharField to be able to hold hashed value
|
|
@@ -222,10 +214,10 @@ class ClassModelManager(models.Manager):
|
|
|
222
214
|
|
|
223
215
|
|
|
224
216
|
class Class(models.Model):
|
|
217
|
+
locked_worksheets: "ManyToManyField[Worksheet]"
|
|
218
|
+
|
|
225
219
|
name = models.CharField(max_length=200)
|
|
226
|
-
teacher = models.ForeignKey(
|
|
227
|
-
Teacher, related_name="class_teacher", on_delete=models.CASCADE
|
|
228
|
-
)
|
|
220
|
+
teacher = models.ForeignKey(Teacher, related_name="class_teacher", on_delete=models.CASCADE)
|
|
229
221
|
access_code = models.CharField(max_length=5, null=True)
|
|
230
222
|
classmates_data_viewable = models.BooleanField(default=False)
|
|
231
223
|
always_accept_requests = models.BooleanField(default=False)
|
|
@@ -249,9 +241,7 @@ class Class(models.Model):
|
|
|
249
241
|
def active_game(self):
|
|
250
242
|
games = self.game_set.filter(game_class=self, is_archived=False)
|
|
251
243
|
if len(games) >= 1:
|
|
252
|
-
assert (
|
|
253
|
-
len(games) == 1
|
|
254
|
-
) # there should NOT be more than one active game
|
|
244
|
+
assert len(games) == 1 # there should NOT be more than one active game
|
|
255
245
|
return games[0]
|
|
256
246
|
return None
|
|
257
247
|
|
|
@@ -261,13 +251,8 @@ class Class(models.Model):
|
|
|
261
251
|
|
|
262
252
|
def get_requests_message(self):
|
|
263
253
|
if self.always_accept_requests:
|
|
264
|
-
external_requests_message =
|
|
265
|
-
|
|
266
|
-
)
|
|
267
|
-
elif (
|
|
268
|
-
self.accept_requests_until is not None
|
|
269
|
-
and (self.accept_requests_until - timezone.now()) >= timedelta()
|
|
270
|
-
):
|
|
254
|
+
external_requests_message = "This class is currently set to always accept requests."
|
|
255
|
+
elif self.accept_requests_until is not None and (self.accept_requests_until - timezone.now()) >= timedelta():
|
|
271
256
|
external_requests_message = (
|
|
272
257
|
"This class is accepting external requests until "
|
|
273
258
|
+ self.accept_requests_until.strftime("%d-%m-%Y %H:%M")
|
|
@@ -275,9 +260,7 @@ class Class(models.Model):
|
|
|
275
260
|
+ timezone.get_current_timezone_name()
|
|
276
261
|
)
|
|
277
262
|
else:
|
|
278
|
-
external_requests_message =
|
|
279
|
-
"This class is not currently accepting external requests."
|
|
280
|
-
)
|
|
263
|
+
external_requests_message = "This class is not currently accepting external requests."
|
|
281
264
|
|
|
282
265
|
return external_requests_message
|
|
283
266
|
|
|
@@ -299,9 +282,7 @@ class UserSession(models.Model):
|
|
|
299
282
|
login_time = models.DateTimeField(default=timezone.now)
|
|
300
283
|
school = models.ForeignKey(School, null=True, on_delete=models.SET_NULL)
|
|
301
284
|
class_field = models.ForeignKey(Class, null=True, on_delete=models.SET_NULL)
|
|
302
|
-
login_type = models.CharField(
|
|
303
|
-
max_length=100, null=True
|
|
304
|
-
) # for student login
|
|
285
|
+
login_type = models.CharField(max_length=100, null=True) # for student login
|
|
305
286
|
|
|
306
287
|
def __str__(self):
|
|
307
288
|
return f"{self.user} login: {self.login_time} type: {self.login_type}"
|
|
@@ -330,9 +311,7 @@ class StudentModelManager(models.Manager):
|
|
|
330
311
|
)
|
|
331
312
|
|
|
332
313
|
def independentStudentFactory(self, name, email, password):
|
|
333
|
-
user = User.objects.create_user(
|
|
334
|
-
username=email, email=email, password=password, first_name=name
|
|
335
|
-
)
|
|
314
|
+
user = User.objects.create_user(username=email, email=email, password=password, first_name=name)
|
|
336
315
|
|
|
337
316
|
user_profile = UserProfile.objects.create(user=user)
|
|
338
317
|
|
|
@@ -391,9 +370,7 @@ class JoinReleaseStudent(models.Model):
|
|
|
391
370
|
JOIN = "join"
|
|
392
371
|
RELEASE = "release"
|
|
393
372
|
|
|
394
|
-
student = models.ForeignKey(
|
|
395
|
-
Student, related_name="student", on_delete=models.CASCADE
|
|
396
|
-
)
|
|
373
|
+
student = models.ForeignKey(Student, related_name="student", on_delete=models.CASCADE)
|
|
397
374
|
# either "release" or "join"
|
|
398
375
|
action_type = models.CharField(max_length=64)
|
|
399
376
|
action_time = models.DateTimeField(default=timezone.now)
|
|
@@ -6,7 +6,7 @@ cfl_common/common/apps.py,sha256=49UXZ3bSkFKvIEOL4zM7y1sAhccQJyRtsoOg5XVd_8Y,129
|
|
|
6
6
|
cfl_common/common/context_processors.py,sha256=X0iuX5qu9kMWa7q8osE9CJ2LgM7pPOYQFGdjm8X3rk0,236
|
|
7
7
|
cfl_common/common/csp_config.py,sha256=9ECOLnp60ENRFAYEEIoYOMhqQzLgfKA-wkWxeUBwDrQ,2824
|
|
8
8
|
cfl_common/common/mail.py,sha256=pIRfUMVoJWxdv74UqToj_0_pTVTC51z6QlFVLI3QBOw,6874
|
|
9
|
-
cfl_common/common/models.py,sha256=
|
|
9
|
+
cfl_common/common/models.py,sha256=bfmdqC8DPy4lq_XDvn0aWAJbNdjfaMkuXu0cHLOyWZI,15835
|
|
10
10
|
cfl_common/common/permissions.py,sha256=gC6RQGZI2QDBbglx-xr_V4Hl2C2nf1V2_uPmEuoEcJo,2416
|
|
11
11
|
cfl_common/common/utils.py,sha256=Nn2Npao9Uqad5Js_IdHwF-ow6wrPNpBLW4AO1LxoEBc,1727
|
|
12
12
|
cfl_common/common/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -108,7 +108,7 @@ example_project/portal_test_settings.py,sha256=7Q7SdosA0Ba85qz-xkAe3EHyMPpSIQ61C
|
|
|
108
108
|
example_project/settings.py,sha256=NjFhtDNLwdY5vhUAtqk9a9m3GRfcuWRVqIqnJ3u0o6E,5658
|
|
109
109
|
example_project/urls.py,sha256=FUTzHPlUS1O5kqMHjL5V4L552N2ln7uTDXcw9wjKUto,422
|
|
110
110
|
example_project/wsgi.py,sha256=U1W6WzZxZaIdYZ5tks7w9fqp5WS5qvn2iThsVcskrWw,829
|
|
111
|
-
portal/__init__.py,sha256=
|
|
111
|
+
portal/__init__.py,sha256=hTIZ_8cc-ggqcFeOYQQKOHudFQCQNQlM4ZltuYIIjD4,22
|
|
112
112
|
portal/admin.py,sha256=RKJizTF6dPJKmGPZw7nZUM0X8jkiTjgyKhLQxtvHJ0I,6148
|
|
113
113
|
portal/app_settings.py,sha256=DhWLQOwM0zVOXE3O5TNKbMM9K6agfLuCsHOdr1J7xEI,651
|
|
114
114
|
portal/backends.py,sha256=2Dss6_WoQwPuDzJUF1yEaTQTNG4eUrD12ujJQ5cp5Tc,812
|
|
@@ -126,7 +126,7 @@ portal/forms/invite_teacher.py,sha256=jkDNcCfkts4_lXRzhcI3xBam21Zn2yX9wMpMVhDtW1
|
|
|
126
126
|
portal/forms/organisation.py,sha256=QcQyd7AiqBmvt4y8uQSQylguUbKOKqo2pjqWIkpWjDg,7433
|
|
127
127
|
portal/forms/play.py,sha256=j_QYAKb4qyW0uy0VUUG49dmzDLINc3jR6ddK-djrbc4,11523
|
|
128
128
|
portal/forms/registration.py,sha256=a-TuzikRc0Q-BAYs3rJ3Sz1wmQ1o_rTEtZmWdF7-xss,6008
|
|
129
|
-
portal/forms/teach.py,sha256=
|
|
129
|
+
portal/forms/teach.py,sha256=wVwHP2odgMmEGGbbPQzak_1tqutcr1GWZcadvC1Bffg,21739
|
|
130
130
|
portal/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
131
131
|
portal/helpers/captcha.py,sha256=Amwg3HZ9eIh1LGYVYWYruk1ccNj6P3nYP_evufOY8BY,254
|
|
132
132
|
portal/helpers/decorators.py,sha256=Bs6AVCvcgxfHLdJVWzTmZpxlYbJZXJh5e9AGRXf7cwo,3617
|
|
@@ -498,7 +498,7 @@ portal/templates/portal/teach/onboarding_students.html,sha256=09q658n7U7Vuzy_M_0
|
|
|
498
498
|
portal/templates/portal/teach/teacher_add_external_student.html,sha256=Lrrh4W3EwxxXKe45kcqzf2BcPxYo_mLahGIQMNJjX9E,2453
|
|
499
499
|
portal/templates/portal/teach/teacher_added_external_student.html,sha256=f18RhP5PCE13yjBTrQTCwPLZnkcZb0bDUZ_Z2Oh3D3I,1189
|
|
500
500
|
portal/templates/portal/teach/teacher_dismiss_students.html,sha256=_5FvvtNjdYpZaM9lDzXrhhTjAD3NK_92kDYzh7xqowI,4283
|
|
501
|
-
portal/templates/portal/teach/teacher_edit_class.html,sha256=
|
|
501
|
+
portal/templates/portal/teach/teacher_edit_class.html,sha256=R25aFNJDDcMzrwQEFRR1EyAc_d6upNPBL1VyQES4ASg,13023
|
|
502
502
|
portal/templates/portal/teach/teacher_edit_student.html,sha256=JNF8JyoZh0J-oKH4dz7SGSxR0t7J1lbTGLvjhNbk2Rw,3237
|
|
503
503
|
portal/templates/portal/teach/teacher_move_all_classes.html,sha256=u9PNJHrKaIXd67vuwhgMmVXumgSnkKH4QKx1bd3O2VY,1780
|
|
504
504
|
portal/templates/portal/teach/teacher_move_students.html,sha256=toBtjtpiCwvxo2FTJX5oZDzJ9batXdi7ty5AiCHnq4s,1591
|
|
@@ -534,7 +534,7 @@ portal/tests/test_2FA.py,sha256=0N4C9Ab3TvO9W__oQLCo-fLDH1Ho3CiGGsSg-2TiZUE,3597
|
|
|
534
534
|
portal/tests/test_admin.py,sha256=AM2dgv8j9m4L-SDO-sMA9tQvQH9GwRBrlwRG9OgqtfI,1451
|
|
535
535
|
portal/tests/test_api.py,sha256=Yo5s_nEGOoG35jA39yZ6nuDOUZvuCZ8o8o8XhZos61w,13819
|
|
536
536
|
portal/tests/test_captcha_forms.py,sha256=Yn_VYO_6jbq6AeKeLcv-YFL1YwXZpU0C3y7SK8fRUm4,1033
|
|
537
|
-
portal/tests/test_class.py,sha256=
|
|
537
|
+
portal/tests/test_class.py,sha256=MfR8fRsi0XjqS5cbeV19y3Be2RVhOLUHsAy_mjm7P70,17644
|
|
538
538
|
portal/tests/test_emails.py,sha256=pLr06j3uMBxP1raoZQWzUTBVFvsEDFtUh85J8OnqCwE,9238
|
|
539
539
|
portal/tests/test_global_forms.py,sha256=A5JpAe4AYK-wpu0o1qU4THmeNv_wr7lhzaMbjz5czpY,1543
|
|
540
540
|
portal/tests/test_helper_methods.py,sha256=-SQCDZm2XUtyXGEp0CHIb_SSC9CPD-XOSnpnY8QclHk,890
|
|
@@ -626,13 +626,13 @@ portal/views/student/edit_account_details.py,sha256=Ba-3D_zzKbX5N01NG5qqBS0ud10B
|
|
|
626
626
|
portal/views/student/play.py,sha256=GMxk65bxWOe1Ds2kb6rvuOd1GoAtt5v_9AihLNXoUL0,8768
|
|
627
627
|
portal/views/teacher/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
628
628
|
portal/views/teacher/dashboard.py,sha256=pjzOOCz29d4VHukaCI5QhkDsu-RPvy7SXC9dDcPo50k,27422
|
|
629
|
-
portal/views/teacher/teach.py,sha256
|
|
629
|
+
portal/views/teacher/teach.py,sha256=KDlQdHwU9YdoK_fikLpWO_qDk3ZlX1elYFiiWHBQm6I,36688
|
|
630
630
|
portal/views/two_factor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
631
631
|
portal/views/two_factor/core.py,sha256=Lk32z2SN2Pg0rRkK-N-LXMvXC1kKKsH3l692kiSDQ4E,964
|
|
632
632
|
portal/views/two_factor/form.py,sha256=lnHNKI-BMlpncTuW3zUzjPaJJNuEra2I_nOam0eOKFY,257
|
|
633
633
|
portal/views/two_factor/profile.py,sha256=SHSg_xHccE5PtD-OfuOkYhREYz_er4bj5ro1RjJ88Yw,393
|
|
634
|
-
codeforlife_portal-8.0.
|
|
635
|
-
codeforlife_portal-8.0.
|
|
636
|
-
codeforlife_portal-8.0.
|
|
637
|
-
codeforlife_portal-8.0.
|
|
638
|
-
codeforlife_portal-8.0.
|
|
634
|
+
codeforlife_portal-8.0.2.dist-info/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
|
|
635
|
+
codeforlife_portal-8.0.2.dist-info/METADATA,sha256=J59Su8ekITC171pvTLCred37bfPFxHSfexP5UOaGFq4,3078
|
|
636
|
+
codeforlife_portal-8.0.2.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110
|
|
637
|
+
codeforlife_portal-8.0.2.dist-info/top_level.txt,sha256=8e5pdsuIoTqEAMqpelHBjGjLbffcBtgOoggmd2q7nMw,41
|
|
638
|
+
codeforlife_portal-8.0.2.dist-info/RECORD,,
|
portal/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "8.0.
|
|
1
|
+
__version__ = "8.0.2"
|