joeni

Minor changes to courses

Author
Maarten 'Vngngdn' Vangeneugden
Date
Nov. 26, 2017, 1:02 a.m.
Hash
1f2fa3814594fb45c0f1e13535e977ccbcf3b38d
Parent
07e85b805e87d9e192d097a329645ca554d9fd37
Modified files
courses/models.py
courses/urls.py
courses/views.py

courses/models.py

9 additions and 1 deletion.

View changes Hide changes
1
1
from django.utils.translation import ugettext_lazy as _
2
2
3
3
class Course(models.Model):
4
4
    """ Represents a course that is taught at the university. """
5
5
    number = models.PositiveSmallIntegerField(
6
6
        primary_key=True,
7
7
        blank=False,
8
8
        help_text=_("The number associated with this course. A leading '0' will be added if the number is smaller than 1000."),
9
9
        )
10
10
    name = models.CharField(
11
11
        max_length=64,
12
12
        blank=False,
13
13
        help_text=_("The name of this course, in the language that it is taught. Translations are for the appropriate template."),
14
14
        )
15
15
    color = models.CharField(
16
16
        max_length=6,
17
17
        blank=False,
18
18
        default=constants.COLORS['uhasselt-default'],
19
19
        help_text=_("The color for this course. Must be an hexadecimal code."),
20
20
        validators=['validate_hex_color'],
21
21
        )
22
22
    slug_name = models.SlugField(
23
23
        blank=False,
24
24
        allow_unicode=True,
25
25
        unique=True,
26
26
        help_text=_("A so-called 'slug name' for this course."),
27
27
        )
28
28
    # TODO: Add a potential thingy magicky to auto fill the slug name on the course name
29
29
    contact_person = models.ForeignKey(
30
30
        "administration.User",
31
31
        on_delete=models.PROTECT,  # A course must have a contact person
32
32
        limit_choices_to={'is_staff': True},
33
33
        null=False,
34
34
        help_text=_("The person to contact regarding this course."),
35
35
        related_name="contact_person",
36
36
        )
37
37
    coordinator = models.ForeignKey(
38
38
        "administration.User",
39
39
        on_delete=models.PROTECT,  # A course must have a coordinator
40
40
        limit_choices_to={'is_staff': True},
41
41
        null=False,
42
42
        help_text=_("The person whom's the coordinator of this course."),
43
43
        related_name="coordinator",
44
44
        )
45
45
    educating_team = models.ManyToManyField(
46
46
        "administration.User",
47
47
        # No on_delete, since M->M cannot be required at database level
48
48
        limit_choices_to={'is_staff': True},
49
49
        #null=False,  # Useless on a M->M
50
50
        help_text=_("The team members of this course."),
51
-
        related_name="educating_team",
+
51
        related_name="educating_team",
52
52
        )
53
53
    language = models.CharField(
54
54
        max_length=64,
55
55
        choices = (
56
56
            ('NL', _("Dutch")),
57
57
            ('EN', _("English")),
58
58
            ('FR', _("French")),
59
59
            ),
60
60
        null=False,
61
61
        help_text=_("The language in which this course is given."),
62
62
        )
63
63
64
64
    def __str__(self):
+
65
        """ Returns a set of all Users that are part of the team of this course. """
+
66
        return set(
+
67
            self.contact_person,
+
68
            self.coordinator,
+
69
            self.educating_team,
+
70
            )
+
71
+
72
    def __str__(self):
65
73
        number = str(self.number)
66
74
        for i in [10,100,1000]:
67
75
            if self.number < i:
68
76
                number = "0" + number
69
77
        return "(" + number + ") " + self.name
70
78
71
79
72
80
class Prerequisite(models.Model):
73
81
    """ Represents a collection of prerequisites a student must have obtained
74
82
    before being allowed to partake in this course.
75
83
    It's possible that, if a student has obtained credits in a certain set of
76
84
    courses, a certain part of the prerequisites do not have to be obtained.
77
85
    Because of this, make a different record for each different set. In other
78
86
    words: If one set of prerequisites is obtained, and another one isn't, BUT
79
87
    they point to the same course, the student is allowed to partake. """
80
88
    course = models.ForeignKey(
81
89
        "Course",
82
90
        on_delete=models.CASCADE,
83
91
        null=False,
84
92
        help_text=_("The course that these prerequisites are for."),
85
93
        related_name="prerequisite_course",
86
94
        )
87
95
    name = models.CharField(
88
96
        max_length=64,
89
97
        blank=True,
90
98
        help_text=_("To specify a name for this set, if necessary."),
91
99
        )
92
100
    sequentialities = models.ManyToManyField(
93
101
        "Course",
94
102
        help_text=_("All courses for which a credit must've been received in order to follow the course."),
95
103
        related_name="sequentialities",
96
104
        )
97
105
    in_curriculum = models.ManyToManyField(
98
106
        "Course",
99
107
        help_text=_("All courses that have to be in the curriculum to follow this. If a credit was achieved, that course can be omitted."),
100
108
        related_name="in_curriculum",
101
109
        )
102
110
    required_study = models.ForeignKey(
103
111
        "Study",
104
112
        on_delete=models.CASCADE,
105
113
        null=True,
106
114
        help_text=_("If one must have a certain amount of obtained ECTS points for a particular course, state that course here."),
107
115
        )
108
116
    ECTS_for_required_study = models.PositiveSmallIntegerField(
109
117
        null=True,
110
118
        help_text=_("The amount of obtained ECTS points for the required course, if any."),
111
119
        )
112
120
113
121
    def __str__(self):
114
122
        if self.name == "":
115
123
            return _("Prerequisites for %(course)s") % {'course': str(self.course)}
116
124
        else:
117
125
            return self.name + " | " + str(self.course)
118
126
119
127
120
128
class CourseProgramme(models.Model):
121
129
    """ It's possible that a course is taught in multiple degree programmes; For
122
130
    example: Calculus can easily be taught to physics and mathematics students
123
131
    alike. In this table, these relations are set up, and the related properties
124
132
    are defined as well. """
125
133
    study = models.ForeignKey(
126
134
        "Study",
127
135
        on_delete=models.CASCADE,
128
136
        null=False,
129
137
        help_text=_("The study in which the course is taught."),
130
138
        )
131
139
    course = models.ForeignKey(
132
140
        "Course",
133
141
        on_delete=models.CASCADE,
134
142
        null=False,
135
143
        help_text=_("The course that this programme is for."),
136
144
        )
137
145
    study_programme = models.ForeignKey(
138
146
        "StudyProgramme",
139
147
        on_delete=models.CASCADE,
140
148
        null=False,
141
149
        help_text=_("The study programme that this course belongs to."),
142
150
        )
143
151
    programme_type = models.CharField(
144
152
        max_length=1,
145
153
        blank=False,
146
154
        choices = (
147
155
            ('C', _("Compulsory")),
148
156
            ('O', _("Optional")),
149
157
            ),
150
158
        help_text=_("Type of this course for this study."),
151
159
        )
152
160
    study_hours = models.PositiveSmallIntegerField(
153
161
        blank=False,
154
162
        help_text=_("The required amount of hours to study this course."),
155
163
        )
156
164
    ECTS = models.PositiveSmallIntegerField(
157
165
        blank=False,
158
166
        help_text=_("The amount of ECTS points attached to this course."),
159
167
        )
160
168
    semester = models.PositiveSmallIntegerField(
161
169
        blank=False,
162
170
        choices = (
163
171
            (1, _("First semester")),
164
172
            (2, _("Second semester")),
165
173
            (3, _("Full year course")),
166
174
            (4, _("Taught in first quarter")),
167
175
            (5, _("Taught in second quarter")),
168
176
            (6, _("Taught in third quarter")),
169
177
            (7, _("Taught in fourth quarter")),
170
178
            ),
171
179
        help_text=_("The period in which this course is being taught in this study."),
172
180
        )
173
181
    year = models.PositiveSmallIntegerField(
174
182
        blank=False,
175
183
        help_text=_("The year in which this course is taught for this study."),
176
184
        )
177
185
    second_chance = models.BooleanField(
178
186
        default=True,
179
187
        help_text=_("Defines if a second chance exam is planned for this course."),
180
188
        )
181
189
    tolerable = models.BooleanField(
182
190
        default=True,
183
191
        help_text=_("Defines if a failed result can be tolerated."),
184
192
        )
185
193
    scoring = models.CharField(
186
194
        max_length=2,
187
195
        choices = (
188
196
            ('N', _("Numerical")),
189
197
            ('FP', _("Fail/Pass")),
190
198
            ),
191
199
        default='N',
192
200
        blank=False,
193
201
        help_text=_("How the obtained score for this course is given."),
194
202
        )
195
203
196
204
    def __str__(self):
197
205
        return str(self.study) + " - " + str(self.course)
198
206
199
207
class Study(models.Model):
200
208
    """ Defines a certain study that can be followed at the university.
201
209
    This also includes abridged study programmes, like transition programmes.
202
210
    Other information, such as descriptions, are kept in the template file
203
211
    of this study, which can be manually edited. Joeni searches for a file
204
212
    with the exact name as the study + ".html". So if the study is called
205
213
    "Bachelor of Informatics", it will search for "Bachelor of Informatics.html".
206
214
    """
207
215
    # Degree types
208
216
    BSc = _("Bachelor of Science")
209
217
    MSc = _("Master of Science")
210
218
    LLB = _("Bachelor of Laws")
211
219
    LLM = _("Master of Laws")
212
220
    ir  = _("Engineer")
213
221
    ing = _("Technological Engineer")
214
222
    # Faculties
215
223
    FoMaLS = _("Faculty of Medicine and Life Sciences")
216
224
    FoS    = _("Faculty of Sciences")
217
225
    FoTS   = _("Faculty of Transportation Sciences")
218
226
    FoAaA  = _("Faculty of Architecture and Arts")
219
227
    FoBE   = _("Faculty of Business Economics")
220
228
    FoET   = _("Faculty of Engineering Technology")
221
229
    FoL    = _("Faculty of Law")
222
230
223
231
    name = models.CharField(
224
232
        max_length=128,
225
233
        blank=False,
226
234
        unique=True,
227
235
        help_text=_("The full name of this study, in the language it's taught in."),
228
236
        )
229
237
    degree_type = models.CharField(
230
238
        max_length=64,
231
239
        choices = (
232
240
            ('BSc', BSc),
233
241
            ('MSc', MSc),
234
242
            ('LL.B', LLB),
235
243
            ('LL.M', LLM),
236
244
            ('ir.', ir ),
237
245
            ('ing.',ing),
238
246
            ),
239
247
        blank=False,
240
248
        help_text=_("The type of degree one obtains upon passing this study."),
241
249
        )
242
250
    language = models.CharField(
243
251
        max_length=64,
244
252
        choices = (
245
253
            ('NL', _("Dutch")),
246
254
            ('EN', _("English")),
247
255
            ('FR', _("French")),
248
256
            ),
249
257
        null=False,
250
258
        help_text=_("The language in which this study is given."),
251
259
        )
252
260
    # Information about exam committee
253
261
    chairman = models.ForeignKey(
254
262
        "administration.User",
255
263
        on_delete=models.PROTECT,
256
264
        null=False,
257
265
        limit_choices_to={'is_staff': True},
258
266
        help_text=_("The chairman of this study."),
259
267
        related_name="chairman",
260
268
        )
261
269
    vice_chairman = models.ForeignKey(
262
270
        "administration.User",
263
271
        on_delete=models.PROTECT,
264
272
        null=False,
265
273
        help_text=_("The vice-chairman of this study."),
266
274
        limit_choices_to={'is_staff': True},
267
275
        related_name="vice_chairman",
268
276
        )
269
277
    secretary = models.ForeignKey(
270
278
        "administration.User",
271
279
        on_delete=models.PROTECT,
272
280
        null=False,
273
281
        help_text=_("The secretary of this study."),
274
282
        limit_choices_to={'is_staff': True},
275
283
        related_name="secretary",
276
284
        )
277
285
    ombuds = models.ForeignKey(
278
286
        "administration.User",
279
287
        on_delete=models.PROTECT,
280
288
        null=False,
281
289
        help_text=_("The ombuds person of this study."),
282
290
        limit_choices_to={'is_staff': True},
283
291
        related_name="ombuds",
284
292
        )
285
293
    vice_ombuds = models.ForeignKey(
286
294
        "administration.User",
287
295
        on_delete=models.PROTECT,
288
296
        null=False,
289
297
        help_text=_("The (replacing) ombuds person of this study."),
290
298
        limit_choices_to={'is_staff': True},
291
299
        related_name="vice_ombuds",
292
300
        )
293
301
    additional_members = models.ManyToManyField(
294
302
        "administration.User",
295
303
        help_text=_("All the other members of the exam committee."),
296
304
        limit_choices_to={'is_staff': True},
297
305
        related_name="additional_members",
298
306
        )
299
307
    faculty = models.CharField(
300
308
        max_length=6,
301
309
        choices = (
302
310
            ('FoS', FoS),
303
311
            ('FoTS', FoTS),
304
312
            ('FoAaA', FoAaA),
305
313
            ('FoBE', FoBE),
306
314
            ('FoMaLS', FoMaLS),
307
315
            ('FoET', FoET),
308
316
            ('FoL', FoL),
309
317
            ),
310
318
        blank=False,
311
319
        help_text=_("The faculty where this study belongs to."),
312
320
        )
313
321
314
322
    #def study_points(self):
315
323
    """ Returns the amount of study points for this year.
316
324
        This value is inferred based on the study programme information
317
325
        records that lists this study as their foreign key. """
318
326
        #total_ECTS = 0
319
327
        #for course in CourseProgramme.objects.filter(study=self):
320
328
            #total_ECTS += course.ECTS
321
329
        #return total_ECTS
322
330
    # XXX: Commented because this is actually something for the StudyProgramme
323
331
    def years(self):
324
332
        """ Returns the amount of years this study takes.
325
333
        This value is inferred based on the study programme information
326
334
        records that lists this study as their foreign key. """
327
335
        highest_year = 0
328
336
        for course in CourseProgramme.objects.filter(study=self):
329
337
            highest_year = max(highest_year, course.year)
330
338
        return highest_year
331
339
332
340
    def students(self):
333
341
        """ Cross references the information stored in the database, and
334
342
        returns all the students that are following this study in this
335
343
        academic year. """
336
344
        return 0  # TODO
337
345
338
346
339
347
    def __str__(self):
340
348
        return self.name
341
349
342
350
class StudyProgramme(models.Model):
343
351
    """ Represents a programme within a certain study.
344
352
    A good example for this is the different specializations, minors, majors, ...
345
353
    one can follow within the same study. Nevertheless, they're all made of
346
354
    a certain set of courses. This table collects all these, and allows one to name
347
355
    them, so they're distinct from one another. """
348
356
    name = models.CharField(
349
357
            max_length=64,
350
358
            blank=False,
351
359
            help_text=_("The name of this programme."),
352
360
            )
353
361
354
362
    def courses(self):
355
363
        """ All courses that are part of this study programme. """
356
364
        programmes = CourseProgramme.objects.filter(study_programme=self)
357
365
        courses = {}
358
366
        for program in programmes:
359
367
            courses.add(program.course)
360
368
        return courses
361
369
362
370
    def study_points(self, year=None):
363
371
        """ Returns the amount of study points this programme contains.
364
372
        Accepts year as an optional argument. If not given, the study points
365
373
        of all years are returned. """
366
374
        programmes = CourseProgramme.objects.filter(study_programme=self)
367
375
        ECTS = 0
368
376
        for program in programmes:
369
377
            if year is None or program.year == year:
370
378
                # XXX: This only works if the used implementation does lazy
371
379
                # evaluation, otherwise this is a type error!
372
380
                ECTS += program.ECTS
373
381
        return ECTS
374
382
375
383
    def __str__(self):
376
384
        return self.name
377
385
378
386
# Tables about things related to the courses:
379
387
380
388
class Assignment(models.Model):
381
389
    """ For courses, it's possible to set up tasks. These tasks are recorded
382
390
    here. """
383
391
    # TODO: Require that only the course team can create assignments for a team.
384
392
    course = models.ForeignKey(
385
393
        "Course",
386
394
        on_delete=models.CASCADE,
387
395
        null=False,
388
396
        #editable=False,
389
397
        db_index=True,
390
398
        help_text=_("The course for which this task is assigned."),
391
399
        )
392
400
    title = models.CharField(
393
401
        max_length=32,
394
402
        blank=False,
395
403
        help_text=_("The title of this assignment."),
396
404
        )
397
405
    information = models.TextField(
398
406
        help_text=_("Any additional information regarding the assignment. Orgmode syntax available."),
399
407
        )
400
408
    deadline = models.DateTimeField(
401
409
        null=False,
402
410
        help_text=_("The date and time this task is due."),
403
411
        )
404
412
    posted = models.DateField(auto_now_add=True)
405
413
    digital_task = models.BooleanField(
406
414
        default=True,
407
415
        help_text=_("This determines whether this assignment requires handing "
408
416
                    "in a digital file."),
409
417
        )
410
418
411
419
    def __str__(self):
412
420
        return str(self.course) +" | "+ str(self.posted)
413
421
414
422
class Announcement(models.Model):
415
423
    """ Courses sometimes have to make announcements for the students. """
416
424
    course = models.ForeignKey(
417
425
        "Course",
418
426
        on_delete=models.CASCADE,
419
427
        null=False,
420
428
        #editable=False,
421
429
        db_index=True,
422
430
        help_text=_("The course for which this announcement is made."),
423
431
        )
424
432
    title = models.CharField(
425
433
        max_length=20,  # Keep It Short & Simple®
426
434
        help_text=_("A quick title for what this is about."),
427
435
        )
428
436
    text = models.TextField(
429
437
        blank=False,
430
438
        help_text=_("The announcement itself. Orgmode syntax available."),
431
439
        )
432
440
    posted = models.DateTimeField(auto_now_add=True)
433
441
434
442
    def __str__(self):
435
443
        return str(self.course) +" | "+ self.posted.strftime("%m/%d")
436
444
437
445
class Upload(models.Model):
438
446
    """ For certain assignments, digital hand-ins may be required. These hand
439
447
    ins are recorded per student in this table. """
440
448
    assignment = models.ForeignKey(
441
449
        "Assignment",
442
450
        on_delete=models.CASCADE,
443
451
        null=False,
444
452
        #editable=False,
445
453
        db_index=True,
446
454
        limit_choices_to={"digital_task": True},
447
455
        help_text=_("For which assignment this upload is."),
448
456
        )
449
457
    # TODO: Try to find a way to require that, if the upload is made,
450
458
    # only students that have this course in their curriculum can upload.
451
459
    student = models.ForeignKey(
452
460
        "administration.User",
453
461
        on_delete=models.CASCADE,
454
462
        null=False,
455
463
        #editable=False,
456
464
        limit_choices_to={"is_student": True},
457
465
        help_text=_("The student who handed this in."),
458
466
        )
459
467
    upload_time = models.DateTimeField(auto_now_add=True)
460
468
    comment = models.TextField(
461
469
        blank=True,
462
470
        help_text=_("If you wish to add an additional comment, state it here."),
463
471
        )
464
472
    file = models.FileField(
465
473
        upload_to="assignments/uploads/%Y/%m/",
466
474
        null=False,
467
475
        #editable=False,
468
476
        help_text=_("The file you want to upload for this assignment."),
469
477
        )
470
478
471
479
472
480
    def __str__(self):
473
481
        deadline = self.assignment.deadline
474
482
        if deadline < self.upload_time:
475
483
            return str(self.assignment.course) +" | "+ str(self.student.number) + _("(OVERDUE)")
476
484
        else:
477
485
            return str(self.assignment.course) +" | "+ str(self.student.number)
478
486
479
487
def item_upload_directory(instance, filename):
480
488
    return "courses/" + instance.course.slug_name + "/"
481
489
class CourseItem(models.Model):
482
490
    """ Reprensents study material for a course that is being shared by the
483
491
    course's education team. """
484
492
    course = models.ForeignKey(
485
493
        Course,
486
494
        on_delete=models.CASCADE,
487
495
        null=False,
488
496
        #editable=False,
489
497
        )
490
498
    file = models.FileField(
491
499
        upload_to=item_upload_directory,
492
500
        null=False,
493
501
        #editable=False,
494
502
        help_text=_("The file you wish to upload."),
495
503
        )
496
504
    timestamp = models.DateTimeField(auto_now_add=True)
497
505
    note = models.TextField(
498
506
        blank=True,
499
507
        help_text=_("If you want to state some additional information about "
500
508
                    "this upload, state it here."),
501
509
        )
502
510
503
511
class StudyGroup(models.Model):
504
512
    """ It may be necessary to make study groups regarding a course. These
505
513
    are recorded here, and blend in seamlessly with the Groups from Agora.
506
514
    Groups that are recorded as a StudyGroup, are given official course status,
507
515
    and thus, cannot be removed until the status of StudyGroup is lifted. """
508
516
    course = models.ForeignKey(
509
517
        "Course",
510
518
        on_delete=models.CASCADE,
511
519
        null=False,
512
520
        #editable=False,
513
521
        db_index=True,
514
522
        help_text=_("The course for which this group is."),
515
523
        )
516
524
    group = models.ForeignKey(
517
525
        "agora.Group",
518
526
        on_delete=models.PROTECT,  # See class documentation
519
527
        null=False,
520
528
        #editable=False,  # Keep the same group
521
529
        help_text=_("The group that will be seen as the study group."),
522
530
        )
523
531
524
532
    def __str__(self):
525
533
        return str(self.course) +" | "+ str(self.group)
526
534

courses/urls.py

0 additions and 3 deletions.

View changes Hide changes
1
1
from . import views
2
2
from django.utils.translation import ugettext_lazy as _
3
3
4
4
urlpatterns = [] + i18n_patterns(
5
5
    path('index', views.main, name='courses-index'),
6
6
    path('<slug:course_slug>', views.course, name='courses-course-index'),
7
7
    path(_('<slug:course_slug>/announcements'), views.announcements, name='courses-announcements'),
8
-
    path(_('<slug:course_slug>/assignments'), views.assignments, name='courses-assignments'),
9
-
    path(_('<slug:course_slug>/course-material'), views.course_material, name='courses-material'),
10
-
    path(_('<slug:course_slug>/<int:assignment_id>/upload'), views.upload, name='courses-upload'),
11
8
    path(_('<slug:course_slug>/new-item'), views.new_item, name='courses-new-item'),
12
9
    path(_('<slug:course_slug>/groups'), views.groups, name='courses-groups'),
13
10
    )
14
11

courses/views.py

28 additions and 4 deletions.

View changes Hide changes
1
1
import datetime
2
2
from django.core.urlresolvers import reverse # Why?
3
3
from django.utils.translation import ugettext as _
4
-
from .models import *
+
4
from .models import *
5
5
import joeni.administration
6
6
7
7
def current_academic_year():
8
8
    """ Returns the current academic year. The year is determined as follows:
9
9
    - If today is before September 15 of the current year, the returned value
10
10
      is the current year - 1.
11
11
    - If today is after September 15 of the current year, but before January 1
12
12
      of the next year, it returns the current year as is.
13
13
    """
14
14
    today = datetime.datetime.now()
15
15
    switch = datetime.datetime.date(datetime.datetime.year, 9, 15)
16
16
    if today < switch:
17
17
        return today.year - 1
18
18
    else:
19
19
        return today.year
20
20
21
21
@login_required
22
22
def index(request):
23
23
    """ Starting page regarding the courses. This serves two specific groups:
24
24
    - Students: Displays all courses that this student has in his/her curriculum
25
25
                for this academic year. Requires the curriculum to be accepted.
26
26
    - Staff: Displays all courses in which the staff member is part of the
27
27
             educating team, or is otherwise related to the course.
28
28
    Users who are not logged in will be sent to the login page.
29
29
    """
30
30
    template = "courses/index.djhtml"
31
31
    courses = set()
32
32
    if request.user.is_student:
33
33
        curricula = administration.models.Curriculum.objects.filter(student=request.user)
34
34
        current_curriculum = curricula.filter(year__year=current_academic_year())
35
35
        courses = current_curriculum.courses
36
36
    elif request.user.is_staff:
37
37
        courses += adminstration.models.Course.filter(contact_person=request.user)
38
-
        courses += adminstration.models.Course.filter(coordinator=request.user)
39
-
        courses += adminstration.models.Course.filter(educating_team__contains=request.user)
40
-
    else:
+
38
    else:
41
39
        raise django.exceptions.FieldError("User "+request.user.number+" is neither staff nor student")
42
40
43
41
    context = {
44
42
        'courses': courses,
45
43
        }
46
44
47
45
    return render(request, template, context)
48
46
49
47
@login_required
50
48
def course(request, course_slug):
51
49
    template = "courses/course.djhtml"
52
50
    course = Course.objects.get(slug_name=course_slug)
53
51
54
52
    # Check if user can see this page
55
53
    if request.user.is_student:
56
54
        curricula = administration.models.Curriculum.objects.filter(student=request.user)
57
55
        current_curriculum = curricula.filter(year__year=current_academic_year())
58
56
        if course not in current_curriculum.courses:
59
57
            """ I'm currently just redirecting to the index page, but maybe it's
60
58
            just as good to make an announcement that this course cannot be
61
59
            used by this user. """
62
60
            return index(request)
63
61
64
62
65
63
66
64
    context = {
67
65
        'course': course,
68
66
        'announcements': Announcement.objects.filter(course=course),
69
67
        'assignments': Assignment.objects.filter(course=course),
70
68
        'course-items': CourseItem.objects.filter(course=course),
71
69
        'study-groups': StudyGroup.objects.filter(course=course),
72
70
        'uploads': Upload.objects.filter(course=course).filter(student=request.user)
73
71
        }
74
72
75
73
    return render(request, template, context)
76
74
+
75
@login_required
+
76
def new_item(request, course_slug):
+
77
    template = "courses/new_item.djhtml"
+
78
    course = Course.objects.get(slug_name=course_slug)
+
79
+
80
    if request.user.is_student or request.user not in course.course_team:
+
81
        # Students can't add new items. Redirect to index
+
82
        # Also redirect people who are not part of the course team
+
83
        redirect('courses-index')
+
84
    # Now able to assume user is allowed to add items to this course
+
85
+
86
    context = {
+
87
        'course': course,
+
88
        'announcements': Announcement.objects.filter(course=course),
+
89
        'assignments': Assignment.objects.filter(course=course),
+
90
        'course-items': CourseItem.objects.filter(course=course),
+
91
        'study-groups': StudyGroup.objects.filter(course=course),
+
92
        'uploads': Upload.objects.filter(course=course)
+
93
        }
+
94
+
95
    return render(request, template, context)
+
96
+
97
@login_required
+
98
def remove(request, type, id):
+
99
    pass
+
100