vkk.workhours.contributor.forms
A collection of Form
s for contributors.
1""" 2A collection of `Form`s for contributors. 3""" 4 5import datetime 6from django import forms 7from vkk.workhours.models import WorkHours, Period, ProjectAssignment 8from vkk.workhours.forms import date_iterator 9 10 11class WorkhourCalendarForm(forms.Form): 12 """ 13 A form for entering work hours resembling a calender. 14 """ 15 class Media: 16 """ 17 An inner class containing meta information for styling. 18 """ 19 css = {'all': ('styles/calendar.css',)} 20 21 template_name_calendar = 'vkk/workhours/contributor/calendar.html' 22 23 def __init__(self, *args, period_pk=None, assignment_pk=None, **kwargs): 24 """ 25 Constructs an `WorkhourCalendarForm` instance using the given primary 26 keys of an `Period` and `ProjectAssignment`. 27 """ 28 super().__init__(*args, **kwargs) 29 self._project_assignment = ProjectAssignment.objects.get( 30 pk=assignment_pk 31 ) 32 33 # create fields 34 self._period = Period.objects.get(pk=period_pk) 35 today = datetime.date.today() 36 field_class = WorkHours.hours.field.formfield 37 38 for date in date_iterator(self._period.start, self._period.end): 39 is_disabled = date > today or self._project_assignment.project.start > date \ 40 or self._project_assignment.project.end < date 41 field = field_class( 42 min_value=0, 43 max_value=24, 44 required=False, 45 label=date.day, 46 label_suffix='', 47 disabled=is_disabled 48 ) 49 self.fields[date.isoformat()] = field 50 51 # provide initial data 52 workhours = WorkHours.objects.filter( 53 period__pk=period_pk, 54 project_assignment__pk=assignment_pk 55 ) 56 for entry in workhours: 57 field = self.fields.get(entry.day.isoformat()) 58 if field is not None: 59 field.initial = entry.hours 60 61 def _get_date_calendar_structure(self): 62 """ 63 Private method used for structuring some data for rendering the form. 64 """ 65 dates = date_iterator(self._period.start, self._period.end) 66 67 # subdevision into months 68 months = [] 69 month_number = -1 70 for date in dates: 71 if date.month != month_number: 72 months += [[]] 73 month_number = date.month 74 months[-1] += [date] 75 76 # subdevision into weeks 77 weeks = [] 78 for month in months: 79 weeks += [[]] 80 week_day = 7 81 for date in month: 82 if date.weekday() < week_day: 83 weeks[-1] += [[]] 84 weeks[-1][-1] += [date] 85 week_day = date.weekday() 86 87 return weeks 88 89 def _get_field_calendar_structure(self): 90 """ 91 Private method used for structuring some data for rendering the form. 92 """ 93 calendar = self._get_date_calendar_structure() 94 return [[( 95 [(day, self[day.isoformat()]) for day in week] 96 ) for week in month] for month in calendar] 97 98 def as_calendar(self): 99 """ 100 Renders the form resembling a calender. 101 """ 102 context = super().get_context() 103 context.update({'fields_more': self._get_field_calendar_structure()}) 104 return self.render( 105 template_name=self.template_name_calendar, 106 context=context 107 ) 108 109 def save(self): 110 """ 111 Tries to create, modify or delete all changes. 112 """ 113 if self.is_valid() and self.has_changed(): 114 add = [] 115 delete = [] 116 for field_name in self.changed_data: 117 initial = self.fields[field_name].initial 118 value = self.cleaned_data.get(field_name) 119 if value is None or value == 0.0: 120 delete.append( 121 datetime.date.fromisoformat(field_name) 122 ) 123 elif initial is None: 124 add.append(WorkHours( 125 project_assignment=self._project_assignment, 126 period=self._period, 127 day=datetime.date.fromisoformat(field_name), 128 hours=value 129 )) 130 else: 131 WorkHours.objects.filter( 132 project_assignment=self._project_assignment, 133 period=self._period, 134 day=datetime.date.fromisoformat(field_name), 135 ).update(hours=value) 136 WorkHours.objects.filter( 137 project_assignment=self._project_assignment, 138 period=self._period, 139 day__in=delete 140 ).delete() 141 WorkHours.objects.bulk_create(add)
class
WorkhourCalendarForm(django.forms.forms.Form):
12class WorkhourCalendarForm(forms.Form): 13 """ 14 A form for entering work hours resembling a calender. 15 """ 16 class Media: 17 """ 18 An inner class containing meta information for styling. 19 """ 20 css = {'all': ('styles/calendar.css',)} 21 22 template_name_calendar = 'vkk/workhours/contributor/calendar.html' 23 24 def __init__(self, *args, period_pk=None, assignment_pk=None, **kwargs): 25 """ 26 Constructs an `WorkhourCalendarForm` instance using the given primary 27 keys of an `Period` and `ProjectAssignment`. 28 """ 29 super().__init__(*args, **kwargs) 30 self._project_assignment = ProjectAssignment.objects.get( 31 pk=assignment_pk 32 ) 33 34 # create fields 35 self._period = Period.objects.get(pk=period_pk) 36 today = datetime.date.today() 37 field_class = WorkHours.hours.field.formfield 38 39 for date in date_iterator(self._period.start, self._period.end): 40 is_disabled = date > today or self._project_assignment.project.start > date \ 41 or self._project_assignment.project.end < date 42 field = field_class( 43 min_value=0, 44 max_value=24, 45 required=False, 46 label=date.day, 47 label_suffix='', 48 disabled=is_disabled 49 ) 50 self.fields[date.isoformat()] = field 51 52 # provide initial data 53 workhours = WorkHours.objects.filter( 54 period__pk=period_pk, 55 project_assignment__pk=assignment_pk 56 ) 57 for entry in workhours: 58 field = self.fields.get(entry.day.isoformat()) 59 if field is not None: 60 field.initial = entry.hours 61 62 def _get_date_calendar_structure(self): 63 """ 64 Private method used for structuring some data for rendering the form. 65 """ 66 dates = date_iterator(self._period.start, self._period.end) 67 68 # subdevision into months 69 months = [] 70 month_number = -1 71 for date in dates: 72 if date.month != month_number: 73 months += [[]] 74 month_number = date.month 75 months[-1] += [date] 76 77 # subdevision into weeks 78 weeks = [] 79 for month in months: 80 weeks += [[]] 81 week_day = 7 82 for date in month: 83 if date.weekday() < week_day: 84 weeks[-1] += [[]] 85 weeks[-1][-1] += [date] 86 week_day = date.weekday() 87 88 return weeks 89 90 def _get_field_calendar_structure(self): 91 """ 92 Private method used for structuring some data for rendering the form. 93 """ 94 calendar = self._get_date_calendar_structure() 95 return [[( 96 [(day, self[day.isoformat()]) for day in week] 97 ) for week in month] for month in calendar] 98 99 def as_calendar(self): 100 """ 101 Renders the form resembling a calender. 102 """ 103 context = super().get_context() 104 context.update({'fields_more': self._get_field_calendar_structure()}) 105 return self.render( 106 template_name=self.template_name_calendar, 107 context=context 108 ) 109 110 def save(self): 111 """ 112 Tries to create, modify or delete all changes. 113 """ 114 if self.is_valid() and self.has_changed(): 115 add = [] 116 delete = [] 117 for field_name in self.changed_data: 118 initial = self.fields[field_name].initial 119 value = self.cleaned_data.get(field_name) 120 if value is None or value == 0.0: 121 delete.append( 122 datetime.date.fromisoformat(field_name) 123 ) 124 elif initial is None: 125 add.append(WorkHours( 126 project_assignment=self._project_assignment, 127 period=self._period, 128 day=datetime.date.fromisoformat(field_name), 129 hours=value 130 )) 131 else: 132 WorkHours.objects.filter( 133 project_assignment=self._project_assignment, 134 period=self._period, 135 day=datetime.date.fromisoformat(field_name), 136 ).update(hours=value) 137 WorkHours.objects.filter( 138 project_assignment=self._project_assignment, 139 period=self._period, 140 day__in=delete 141 ).delete() 142 WorkHours.objects.bulk_create(add)
A form for entering work hours resembling a calender.
WorkhourCalendarForm(*args, period_pk=None, assignment_pk=None, **kwargs)
24 def __init__(self, *args, period_pk=None, assignment_pk=None, **kwargs): 25 """ 26 Constructs an `WorkhourCalendarForm` instance using the given primary 27 keys of an `Period` and `ProjectAssignment`. 28 """ 29 super().__init__(*args, **kwargs) 30 self._project_assignment = ProjectAssignment.objects.get( 31 pk=assignment_pk 32 ) 33 34 # create fields 35 self._period = Period.objects.get(pk=period_pk) 36 today = datetime.date.today() 37 field_class = WorkHours.hours.field.formfield 38 39 for date in date_iterator(self._period.start, self._period.end): 40 is_disabled = date > today or self._project_assignment.project.start > date \ 41 or self._project_assignment.project.end < date 42 field = field_class( 43 min_value=0, 44 max_value=24, 45 required=False, 46 label=date.day, 47 label_suffix='', 48 disabled=is_disabled 49 ) 50 self.fields[date.isoformat()] = field 51 52 # provide initial data 53 workhours = WorkHours.objects.filter( 54 period__pk=period_pk, 55 project_assignment__pk=assignment_pk 56 ) 57 for entry in workhours: 58 field = self.fields.get(entry.day.isoformat()) 59 if field is not None: 60 field.initial = entry.hours
Constructs an WorkhourCalendarForm
instance using the given primary
keys of an Period
and ProjectAssignment
.
def
as_calendar(self):
99 def as_calendar(self): 100 """ 101 Renders the form resembling a calender. 102 """ 103 context = super().get_context() 104 context.update({'fields_more': self._get_field_calendar_structure()}) 105 return self.render( 106 template_name=self.template_name_calendar, 107 context=context 108 )
Renders the form resembling a calender.
def
save(self):
110 def save(self): 111 """ 112 Tries to create, modify or delete all changes. 113 """ 114 if self.is_valid() and self.has_changed(): 115 add = [] 116 delete = [] 117 for field_name in self.changed_data: 118 initial = self.fields[field_name].initial 119 value = self.cleaned_data.get(field_name) 120 if value is None or value == 0.0: 121 delete.append( 122 datetime.date.fromisoformat(field_name) 123 ) 124 elif initial is None: 125 add.append(WorkHours( 126 project_assignment=self._project_assignment, 127 period=self._period, 128 day=datetime.date.fromisoformat(field_name), 129 hours=value 130 )) 131 else: 132 WorkHours.objects.filter( 133 project_assignment=self._project_assignment, 134 period=self._period, 135 day=datetime.date.fromisoformat(field_name), 136 ).update(hours=value) 137 WorkHours.objects.filter( 138 project_assignment=self._project_assignment, 139 period=self._period, 140 day__in=delete 141 ).delete() 142 WorkHours.objects.bulk_create(add)
Tries to create, modify or delete all changes.
Inherited Members
- django.forms.forms.BaseForm
- default_renderer
- field_order
- prefix
- use_required_attribute
- template_name_div
- template_name_p
- template_name_table
- template_name_ul
- template_name_label
- is_bound
- data
- files
- auto_id
- initial
- error_class
- label_suffix
- empty_permitted
- fields
- renderer
- order_fields
- errors
- is_valid
- add_prefix
- add_initial_prefix
- template_name
- get_context
- non_field_errors
- add_error
- has_error
- full_clean
- clean
- has_changed
- changed_data
- is_multipart
- visible_fields
- get_initial_for_field
- django.forms.utils.RenderableFormMixin
- as_p
- as_table
- as_ul
- as_div
- django.forms.utils.RenderableMixin
- render
class
WorkhourCalendarForm.Media:
16 class Media: 17 """ 18 An inner class containing meta information for styling. 19 """ 20 css = {'all': ('styles/calendar.css',)}
An inner class containing meta information for styling.