def view_volunteers(request, shift_id): user = request.user admin = None try: admin = user.administrator except ObjectDoesNotExist: pass # check that an admin is logged in if not admin: return render(request, 'vms/no_admin_rights.html') else: if shift_id: shift = get_shift_by_id(shift_id) if shift: volunteer_list = get_volunteers_by_shift_id(shift_id) logged_volunteer_list = get_logged_volunteers_by_shift_id( shift_id) slots_remaining = get_shift_slots_remaining(shift_id) return render( request, 'shift/list_volunteers.html', { 'volunteer_list': volunteer_list, 'shift': shift, 'slots_remaining': slots_remaining, 'logged_volunteer_list': logged_volunteer_list }) else: raise Http404 else: raise Http404
def form_valid(self, form): edit_request_id = self.kwargs['edit_request_id'] edit_request = EditRequest.objects.get(pk=edit_request_id) volunteer_id = self.kwargs['volunteer_id'] volunteer = get_volunteer_by_id(volunteer_id) shift_id = self.kwargs['shift_id'] shift = get_shift_by_id(shift_id) event = shift.job.event start_time = form.cleaned_data['start_time'] end_time = form.cleaned_data['end_time'] shift_start_time = shift.start_time shift_end_time = shift.end_time try: if end_time > start_time: if (start_time >= shift_start_time and end_time <= shift_end_time): edit_shift_hours(volunteer_id, shift_id, start_time, end_time) vol_email = volunteer.email message = render_to_string( 'shift/request_status.html', { 'volunteer_first_name': volunteer.first_name, 'event': event }) try: send_mail("Log Hours Edited", message, "*****@*****.**", [vol_email]) except Exception: raise Exception("There was an error in sending mail.") return HttpResponseRedirect( reverse('shift:manage_volunteer_shifts', args=(volunteer_id, ))) else: messages.add_message( self.request, messages.INFO, 'Logged hours should be between shift hours') return render( self.request, 'shift/edit_hours_manager.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'edit_request_id': edit_request_id, }) else: messages.add_message( self.request, messages.INFO, 'End time should be greater than start time') return render( self.request, 'shift/edit_hours_manager.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'edit_request_id': edit_request_id, }) except Exception: raise Http404
def view_volunteers(request, shift_id): user = request.user admin = None try: admin = user.administrator except ObjectDoesNotExist: pass # check that an admin is logged in if not admin: return render(request, 'vms/no_admin_rights.html') else: if shift_id: shift = get_shift_by_id(shift_id) if shift: volunteer_list = get_volunteers_by_shift_id(shift_id) logged_volunteer_list = \ get_logged_volunteers_by_shift_id(shift_id) slots_remaining = get_shift_slots_remaining(shift_id) return render( request, 'shift/list_volunteers.html', { 'volunteer_list': volunteer_list, 'shift': shift, 'slots_remaining': slots_remaining, 'logged_volunteer_list': logged_volunteer_list }) else: raise Http404 else: raise Http404
def get_context_data(self, **kwargs): context = super(EditHoursManagerView, self).get_context_data(**kwargs) volunteer_id = self.kwargs['volunteer_id'] shift_id = self.kwargs['shift_id'] context['volunteer_shift'] = \ get_volunteer_shift_by_id(volunteer_id, shift_id) context['shift'] = get_shift_by_id(shift_id) return context
def get_context_data(self, **kwargs): context = super(AddHoursView, self).get_context_data(**kwargs) shift_id = self.kwargs['shift_id'] volunteer_id = self.kwargs['volunteer_id'] context['volunteer_id'] = volunteer_id context['shift_id'] = shift_id context['shift'] = get_shift_by_id(shift_id) return context
def get_context_data(self, **kwargs): context = super(EditHoursManagerView, self).get_context_data(**kwargs) volunteer_id = self.kwargs['volunteer_id'] shift_id = self.kwargs['shift_id'] context['volunteer_shift'] = get_volunteer_shift_by_id( volunteer_id, shift_id) context['shift'] = get_shift_by_id(shift_id) return context
def sign_up(request, shift_id, volunteer_id): if shift_id: shift = get_shift_by_id(shift_id) if shift: user = request.user admin = None volunteer = None try: admin = user.administrator except ObjectDoesNotExist: pass try: volunteer = user.volunteer except ObjectDoesNotExist: pass if not admin and not volunteer: return HttpResponse(status=403) if volunteer: if (int(volunteer.id) != int(volunteer_id)): return HttpResponse(status=403) if request.method == 'POST': try: result = register(volunteer_id, shift_id) if result == "IS_VALID": if admin: return HttpResponseRedirect( reverse('shift:manage_volunteer_shifts', args=(volunteer_id, ))) if volunteer: return HttpResponseRedirect( reverse('shift:view_volunteer_shifts', args=(volunteer_id, ))) else: return render(request, 'shift/sign_up_error.html', {'error_code': result}) except ObjectDoesNotExist: raise Http404 else: return render(request, 'shift/sign_up.html', { 'shift': shift, 'volunteer_id': volunteer_id }) else: raise Http404 else: raise Http404
def form_valid(self, form): volunteer_id = self.kwargs['volunteer_id'] shift_id = self.kwargs['shift_id'] shift = get_shift_by_id(shift_id) volunteer_shift = get_volunteer_shift_by_id(volunteer_id, shift_id) start_time = form.cleaned_data['start_time'] end_time = form.cleaned_data['end_time'] shift_start_time = shift.start_time shift_end_time = shift.end_time try: if (end_time > start_time): if (start_time >= shift_start_time and end_time <= shift_end_time): edit_shift_hours(volunteer_id, shift_id, start_time, end_time) return HttpResponseRedirect( reverse( 'shift:manage_volunteer_shifts', args=(volunteer_id, ))) else: messages.add_message( self.request, messages.INFO, 'Logged hours should be between shift hours') return render( self.request, 'shift/edit_hours_manager.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'volunteer_shift': volunteer_shift, }) else: messages.add_message( self.request, messages.INFO, 'End time should be greater than start time') return render( self.request, 'shift/edit_hours_manager.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'volunteer_shift': volunteer_shift, }) except: raise Http404
def form_valid(self, form): volunteer_id = self.kwargs['volunteer_id'] shift_id = self.kwargs['shift_id'] shift = get_shift_by_id(shift_id) volunteer_shift = get_volunteer_shift_by_id(volunteer_id, shift_id) start_time = form.cleaned_data['start_time'] end_time = form.cleaned_data['end_time'] shift_start_time = shift.start_time shift_end_time = shift.end_time try: if end_time > start_time: if (start_time >= shift_start_time and end_time <= shift_end_time): edit_shift_hours(volunteer_id, shift_id, start_time, end_time) return HttpResponseRedirect( reverse('shift:manage_volunteer_shifts', args=(volunteer_id, ))) else: messages.add_message( self.request, messages.INFO, 'Logged hours should be between shift hours') return render( self.request, 'shift/edit_hours_manager.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'volunteer_shift': volunteer_shift, }) else: messages.add_message( self.request, messages.INFO, 'End time should be greater than start time') return render( self.request, 'shift/edit_hours_manager.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'volunteer_shift': volunteer_shift, }) except: raise Http404
def test_get_shift_by_id(self): """ Uses shifts s1 and s2 """ # test typical cases self.assertIsNotNone(get_shift_by_id(self.s1.id)) self.assertIsNotNone(get_shift_by_id(self.s2.id)) self.assertEqual(get_shift_by_id(self.s1.id), self.s1) self.assertEqual(get_shift_by_id(self.s2.id), self.s2) # test non-existant cases self.assertIsNone(get_shift_by_id(100)) self.assertIsNone(get_shift_by_id(200))
def form_valid(self, form): shift_id = self.kwargs['shift_id'] shift = get_shift_by_id(shift_id) job = shift.job start_date_job = job.start_date end_date_job = job.end_date shift_date = form.cleaned_data['date'] shift_start_time = form.cleaned_data['start_time'] shift_end_time = form.cleaned_data['end_time'] max_vols = form.cleaned_data['max_volunteers'] # save when all conditions satisfied if (start_date_job <= shift_date <= end_date_job and shift_end_time > shift_start_time and max_vols >= len(shift.volunteers.all())): shift_to_edit = form.save(commit=False) shift_to_edit.job = job shift_to_edit.save() return HttpResponseRedirect( reverse('shift:list_shifts', args=(shift.job.id, ))) else: if shift_date < start_date_job or shift_date > end_date_job: messages.add_message(self.request, messages.INFO, 'Shift date should lie within Job dates') if shift_end_time <= shift_start_time: messages.add_message( self.request, messages.INFO, 'Shift end time should be greater than start time') if max_vols < len(shift.volunteers.all()): messages.add_message( self.request, messages.INFO, 'Max volunteers should be greater than or equal to' ' the already assigned volunteers.') return render(self.request, 'shift/edit.html', { 'form': form, 'shift': shift, 'job': shift.job })
def form_valid(self, form): shift_id = self.kwargs['shift_id'] shift = get_shift_by_id(shift_id) job = shift.job start_date_job = job.start_date end_date_job = job.end_date shift_date = form.cleaned_data['date'] shift_start_time = form.cleaned_data['start_time'] shift_end_time = form.cleaned_data['end_time'] max_vols = form.cleaned_data['max_volunteers'] # save when all conditions satisfied if (shift_date >= start_date_job and shift_date <= end_date_job and shift_end_time > shift_start_time \ and max_vols >= len(shift.volunteers.all())): shift_to_edit = form.save(commit=False) shift_to_edit.job = job shift_to_edit.save() return HttpResponseRedirect( reverse('shift:list_shifts', args=(shift.job.id, ))) else: if (shift_date < start_date_job or shift_date > end_date_job): messages.add_message(self.request, messages.INFO, 'Shift date should lie within Job dates') if shift_end_time <= shift_start_time: messages.add_message( self.request, messages.INFO, 'Shift end time should be greater than start time') if max_vols < len(shift.volunteers.all()): messages.add_message( self.request, messages.INFO, 'Max volunteers should be greater than or equal to' ' the already assigned volunteers.') return render(self.request, 'shift/edit.html', { 'form': form, 'shift': shift, 'job': shift.job })
def sign_up(request, shift_id, volunteer_id): if shift_id: shift = get_shift_by_id(shift_id) if shift: user = request.user admin = None volunteer = None try: admin = user.administrator except ObjectDoesNotExist: pass try: volunteer = user.volunteer except ObjectDoesNotExist: pass if not admin and not volunteer: return HttpResponse(status=403) if volunteer: if (int(volunteer.id) != int(volunteer_id)): return HttpResponse(status=403) if request.method == 'POST': try: result = register(volunteer_id, shift_id) if result == "IS_VALID": if admin: vol_email = Volunteer.objects.get( pk=volunteer_id).email shift_object = get_shift_by_id(shift_id) job_object = Job.objects.get(shift=shift_object) event_object = Event.objects.get(job=job_object) message = render_to_string( 'shift/sign_up_email.txt', { 'admin_first_name': admin.first_name, 'admin_last_name': admin.last_name, 'shift_start_time': shift_object.start_time, 'shift_end_time': shift_object.end_time, 'admin_email': admin.email, 'job_name': job_object.name, 'event_name': event_object.name, 'shift_date': shift_object.date, }) try: send_mail("Shift Assigned", message, "*****@*****.**", [vol_email], fail_silently=False) except: raise Exception("There was an error in sending email.") return HttpResponseRedirect( reverse( 'shift:manage_volunteer_shifts', args=(volunteer_id, ))) if volunteer: return HttpResponseRedirect( reverse( 'shift:view_volunteer_shifts', args=(volunteer_id, ))) else: return render(request, 'shift/sign_up_error.html', { 'error_code': result }) except ObjectDoesNotExist: raise Http404 else: return render(request, 'shift/sign_up.html', { 'shift': shift, 'volunteer_id': volunteer_id }) else: raise Http404 else: raise Http404
def cancel(request, shift_id, volunteer_id): if shift_id and volunteer_id: user = request.user admin = None volunteer = None try: admin = user.administrator except ObjectDoesNotExist: pass try: volunteer = user.volunteer except ObjectDoesNotExist: pass # check that either an admin or volunteer is logged in if not admin and not volunteer: return render(request, 'vms/no_volunteer_rights.html', status=403) # if a volunteer is logged in, # verify that they are canceling their own shift if volunteer: if int(volunteer.id) != int(volunteer_id): return render(request, 'vms/no_volunteer_rights.html', status=403) if request.method == 'POST': try: cancel_shift_registration(volunteer_id, shift_id) if admin: vol_email = Volunteer.objects.get(pk=volunteer_id).email shift_object = get_shift_by_id(shift_id) job_object = Job.objects.get(shift=shift_object) event_object = Event.objects.get(job=job_object) message = render_to_string( 'shift/cancel_email.txt', { 'admin_first_name': admin.first_name, 'admin_last_name': admin.last_name, 'shift_start_time': shift_object.start_time, 'shift_end_time': shift_object.end_time, 'admin_email': admin.email, 'job_name': job_object.name, 'event_name': event_object.name, 'shift_date': shift_object.date, }) try: send_mail("Shift Cancelled", message, "*****@*****.**", [vol_email]) except Exception: raise Exception("There was an error in sending email.") return HttpResponseRedirect( reverse('shift:manage_volunteer_shifts', args=(volunteer_id, ))) elif volunteer: return HttpResponseRedirect( reverse('shift:view_volunteer_shifts', args=(volunteer_id, ))) else: raise Http404 except Exception: raise Http404 else: return render(request, 'shift/cancel_shift.html', { 'shift_id': shift_id, 'volunteer_id': volunteer_id }) else: raise Http404
def get_context_data(self, **kwargs): context = super(ShiftUpdateView, self).get_context_data(**kwargs) shift = get_shift_by_id(self.kwargs['shift_id']) context['shift'] = shift context['job'] = shift.job return context
def form_valid(self, form): edit_request_id = self.kwargs['edit_request_id'] edit_request = EditRequest.objects.get(pk=edit_request_id) volunteer_id = self.kwargs['volunteer_id'] volunteer = get_volunteer_by_id(volunteer_id) shift_id = self.kwargs['shift_id'] shift = get_shift_by_id(shift_id) event = shift.job.event start_time = form.cleaned_data['start_time'] end_time = form.cleaned_data['end_time'] shift_start_time = shift.start_time shift_end_time = shift.end_time try: if (end_time > start_time): if (start_time >= shift_start_time and end_time <= shift_end_time): edit_shift_hours(volunteer_id, shift_id, start_time, end_time) vol_email = volunteer.email message = render_to_string('shift/request_status.html', {'volunteer_first_name': volunteer.first_name, 'event': event }) try: send_mail("Log Hours Edited", message, "*****@*****.**", [vol_email]) except: raise Exception("There was an error in sending mail.") return HttpResponseRedirect( reverse( 'shift:manage_volunteer_shifts', args=(volunteer_id, ))) else: messages.add_message( self.request, messages.INFO, 'Logged hours should be between shift hours') return render( self.request, 'shift/edit_hours_manager.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'volunteer_shift': volunteer_shift, 'edit_request_id': edit_request_id, }) else: messages.add_message( self.request, messages.INFO, 'End time should be greater than start time') return render( self.request, 'shift/edit_hours_manager.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'volunteer_shift': volunteer_shift, 'edit_request_id': edit_request_id, }) except: raise Http404
def form_valid(self, form): volunteer_id = self.kwargs['volunteer_id'] shift_id = self.kwargs['shift_id'] shift = get_shift_by_id(shift_id) volunteer_shift = get_volunteer_shift_by_id(volunteer_id, shift_id) volunteer = get_volunteer_by_id(volunteer_id) start_time = form.cleaned_data['start_time'] end_time = form.cleaned_data['end_time'] shift_start_time = shift.start_time shift_end_time = shift.end_time event = shift.job.event site = get_current_site(self.request) try: if (end_time > start_time): if (start_time >= shift_start_time and end_time <= shift_end_time): request = form.save(commit=False) request.volunteer_shift = volunteer_shift request.save() message = render_to_string('shift/request_admin.html', {'volunteer': volunteer, 'new_start_time': start_time, 'new_end_time': end_time, 'original_start_time': shift_start_time, 'original_end_time': shift_end_time, 'event': event, 'edit_request': request, 'shift_id': shift_id, 'domain': site.domain, }) try: send_mail("Edit request", message, "*****@*****.**", ["*****@*****.**"]) except: raise Exception("There was an error in sending the email.") volunteer_shift.edit_requested = True volunteer_shift.save() return HttpResponseRedirect( reverse('shift:view_hours', args=(volunteer_id, ))) else: messages.add_message( self.request, messages.INFO, 'Logged hours should be between shift hours') return render( self.request, 'shift/edit_hours.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'volunteer_shift': volunteer_shift, }) else: messages.add_message( self.request, messages.INFO, 'End time should be greater than start time') return render( self.request, 'shift/edit_hours.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'volunteer_shift': volunteer_shift, }) except: raise Http404
def cancel(request, shift_id, volunteer_id): if shift_id and volunteer_id: user = request.user admin = None volunteer = None try: admin = user.administrator except ObjectDoesNotExist: pass try: volunteer = user.volunteer except ObjectDoesNotExist: pass # check that either an admin or volunteer is logged in if not admin and not volunteer: return render(request, 'vms/no_volunteer_rights.html', status=403) # if a volunteer is logged in, verify that they are canceling their own shift if volunteer: if (int(volunteer.id) != int(volunteer_id)): return render( request, 'vms/no_volunteer_rights.html', status=403) if request.method == 'POST': try: cancel_shift_registration(volunteer_id, shift_id) if admin: vol_email = Volunteer.objects.get(pk=volunteer_id).email shift_object = get_shift_by_id(shift_id) job_object = Job.objects.get(shift=shift_object) event_object = Event.objects.get(job=job_object) message = render_to_string( 'shift/cancel_email.txt', { 'admin_first_name': admin.first_name, 'admin_last_name': admin.last_name, 'shift_start_time': shift_object.start_time, 'shift_end_time': shift_object.end_time, 'admin_email': admin.email, 'job_name': job_object.name, 'event_name': event_object.name, 'shift_date': shift_object.date, }) try: send_mail("Shift Cancelled", message, "*****@*****.**", [vol_email]) except: raise Exception("There was an error in sending email.") return HttpResponseRedirect( reverse( 'shift:manage_volunteer_shifts', args=(volunteer_id, ))) elif volunteer: return HttpResponseRedirect( reverse( 'shift:view_volunteer_shifts', args=(volunteer_id, ))) else: raise Http404 except: raise Http404 else: return render(request, 'shift/cancel_shift.html', { 'shift_id': shift_id, 'volunteer_id': volunteer_id }) else: raise Http404
def test_get_shift_by_id(self): e1 = Event(name="Open Source Event", start_date="2012-10-22", end_date="2012-10-23") e1.save() j1 = Job( name="Software Developer", start_date="2012-10-22", end_date="2012-10-23", description="A software job", event=e1, ) j1.save() s1 = Shift(date="2012-10-23", start_time="9:00", end_time="3:00", max_volunteers=1, job=j1) s2 = Shift(date="2012-10-23", start_time="10:00", end_time="4:00", max_volunteers=2, job=j1) s3 = Shift(date="2012-10-23", start_time="12:00", end_time="6:00", max_volunteers=4, job=j1) s1.save() s2.save() s3.save() # test typical cases self.assertIsNotNone(get_shift_by_id(s1.id)) self.assertIsNotNone(get_shift_by_id(s2.id)) self.assertIsNotNone(get_shift_by_id(s3.id)) self.assertEqual(get_shift_by_id(s1.id), s1) self.assertEqual(get_shift_by_id(s2.id), s2) self.assertEqual(get_shift_by_id(s3.id), s3) # test non-existant cases self.assertIsNone(get_shift_by_id(100)) self.assertIsNone(get_shift_by_id(200)) self.assertIsNone(get_shift_by_id(300)) self.assertIsNone(get_shift_by_id(400)) self.assertNotEqual(get_shift_by_id(100), s1) self.assertNotEqual(get_shift_by_id(100), s2) self.assertNotEqual(get_shift_by_id(100), s3) self.assertNotEqual(get_shift_by_id(200), s1) self.assertNotEqual(get_shift_by_id(200), s2) self.assertNotEqual(get_shift_by_id(200), s3) self.assertNotEqual(get_shift_by_id(300), s1) self.assertNotEqual(get_shift_by_id(300), s2) self.assertNotEqual(get_shift_by_id(300), s3)
def sign_up(request, shift_id, volunteer_id): if shift_id: shift = get_shift_by_id(shift_id) if shift: user = request.user admin = None volunteer = None try: admin = user.administrator except ObjectDoesNotExist: pass try: volunteer = user.volunteer except ObjectDoesNotExist: pass if not admin and not volunteer: return HttpResponse(status=403) if volunteer: if int(volunteer.id) != int(volunteer_id): return HttpResponse(status=403) if request.method == 'POST': try: result = register(volunteer_id, shift_id) if result == "IS_VALID": if admin: vol_email = Volunteer.objects.get( pk=volunteer_id).email shift_object = get_shift_by_id(shift_id) job_object = Job.objects.get(shift=shift_object) event_object = Event.objects.get(job=job_object) message = render_to_string( 'shift/sign_up_email.txt', { 'admin_first_name': admin.first_name, 'admin_last_name': admin.last_name, 'shift_start_time': shift_object.start_time, 'shift_end_time': shift_object.end_time, 'admin_email': admin.email, 'job_name': job_object.name, 'event_name': event_object.name, 'shift_date': shift_object.date, }) try: send_mail("Shift Assigned", message, "*****@*****.**", [vol_email], fail_silently=False) except Exception: raise Exception( "There was an error in sending email.") return HttpResponseRedirect( reverse('shift:manage_volunteer_shifts', args=(volunteer_id, ))) if volunteer: return HttpResponseRedirect( reverse('shift:view_volunteer_shifts', args=(volunteer_id, ))) else: return render(request, 'shift/sign_up_error.html', {'error_code': result}) except ObjectDoesNotExist: raise Http404 else: return render(request, 'shift/sign_up.html', { 'shift': shift, 'volunteer_id': volunteer_id }) else: raise Http404 else: raise Http404
def form_valid(self, form): volunteer_id = self.kwargs['volunteer_id'] shift_id = self.kwargs['shift_id'] shift = get_shift_by_id(shift_id) volunteer_shift = get_volunteer_shift_by_id(volunteer_id, shift_id) volunteer = get_volunteer_by_id(volunteer_id) start_time = form.cleaned_data['start_time'] end_time = form.cleaned_data['end_time'] shift_start_time = shift.start_time shift_end_time = shift.end_time event = shift.job.event site = get_current_site(self.request) try: if end_time > start_time: if (start_time >= shift_start_time and end_time <= shift_end_time): request = form.save(commit=False) request.volunteer_shift = volunteer_shift request.save() message = render_to_string( 'shift/request_admin.html', { 'volunteer': volunteer, 'new_start_time': start_time, 'new_end_time': end_time, 'original_start_time': shift_start_time, 'original_end_time': shift_end_time, 'event': event, 'edit_request': request, 'shift_id': shift_id, 'domain': site.domain, }) try: send_mail("Edit request", message, "*****@*****.**", ["*****@*****.**"]) except Exception: raise Exception( "There was an error in sending the email.") volunteer_shift.edit_requested = True volunteer_shift.save() return HttpResponseRedirect( reverse('shift:view_hours', args=(volunteer_id, ))) else: messages.add_message( self.request, messages.INFO, 'Logged hours should be between shift hours') return render( self.request, 'shift/edit_hours.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'volunteer_shift': volunteer_shift, }) else: messages.add_message( self.request, messages.INFO, 'End time should be greater than start time') return render( self.request, 'shift/edit_hours.html', { 'form': form, 'shift_id': shift_id, 'volunteer_id': volunteer_id, 'shift': shift, 'volunteer_shift': volunteer_shift, }) except Exception: raise Http404