Skip to content

views

main.views ¤

Views for the main app.

Classes¤

CapacitiesListView ¤

Bases: LoginRequiredMixin, PermissionRequiredMixin, SingleTableMixin, FilterView

View to display the list of capacities.

CapacityPlanningView ¤

Bases: LoginRequiredMixin, TemplateView

View that renders the Capacity Planning page.

Functions¤
get_context_data(**kwargs) ¤

Add HTML components and Bokeh version to the context.

Source code in main/views.py
188
189
190
191
192
193
194
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:  # type: ignore
    """Add HTML components and Bokeh version to the context."""
    context = super().get_context_data(**kwargs)
    layout = plots.create_capacity_planning_layout()
    context.update(plots.html_components_from_plot(layout))
    context["bokeh_version"] = bokeh.__version__
    return context

CostRecoveryView ¤

Bases: LoginRequiredMixin, FormView

View that renders the Cost Recovery page.

Functions¤
form_valid(form) ¤

Generate csv using the dates provided in the form.

Source code in main/views.py
203
204
205
206
207
208
def form_valid(self, form: Form) -> HttpResponse:
    """Generate csv using the dates provided in the form."""
    month = form.cleaned_data["month"]
    year = form.cleaned_data["year"]
    response = report.create_charges_report_for_download(month, year)
    return response
get_context_data(**kwargs) ¤

Add HTML components and Bokeh version to the context.

Source code in main/views.py
210
211
212
213
214
215
216
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:  # type: ignore
    """Add HTML components and Bokeh version to the context."""
    context = super().get_context_data(**kwargs)
    layout = plots.create_cost_recovery_layout()
    context.update(plots.html_components_from_plot(layout))
    context["bokeh_version"] = bokeh.__version__
    return context

CustomBaseDetailView ¤

Bases: LoginRequiredMixin, UpdateView

Detail view based on a read-only form view.

While there is a generic Detail View, it is not rendered nicely easily as the bootstrap theme needs to be applied on a field by field basis. So we use a form view instead, which can easily be styled, and make the form read only.

Functions¤
get_form(form_class=None) ¤

Customize form to make it read-only.

Parameters:

Name Type Description Default
form_class Any | None

The form class to use, if any.

None
Return

A form associated to the model.

Source code in main/views.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
def get_form(self, form_class: Any | None = None) -> ModelForm:  # type: ignore
    """Customize form to make it read-only.

    Args:
        form_class: The form class to use, if any.

    Return:
        A form associated to the model.
    """
    form = super().get_form(form_class)

    for field in form.fields.keys():
        form.fields[field].widget.attrs["disabled"] = True
        form.fields[field].widget.attrs["readonly"] = True

    return form

FundingCreateView ¤

Bases: PermissionRequiredMixin, CreateView

View to create a new funding.

FundingDetailView ¤

Bases: PermissionRequiredMixin, CustomBaseDetailView

View to view details of project funding.

Functions¤
get_context_data(**kwargs) ¤

Add funding name to the context, so it is easy to retrieve.

Source code in main/views.py
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:  # type: ignore
    """Add funding name to the context, so it is easy to retrieve."""
    context = super().get_context_data(**kwargs)
    funding = self.get_object()
    context["funding_name"] = str(funding)

    # Monthly charges table for this funding
    charges_qs = models.MonthlyCharge.objects.filter(funding=funding).order_by(
        "-date"
    )
    charges_table = tables.MonthlyChargeTable(charges_qs)
    RequestConfig(self.request).configure(charges_table)
    context["monthly_charges_table"] = charges_table

    return context

FundingListView ¤

Bases: LoginRequiredMixin, PermissionRequiredMixin, SingleTableMixin, ListView

View to display the funding list for all projects.

FundingUpdateView ¤

Bases: PermissionRequiredMixin, UpdateView

Update view based on a form from the Funding model.

Functions¤
get_success_url() ¤

Django magic function to obtain a dynamic success URL.

Source code in main/views.py
298
299
300
def get_success_url(self):  # type: ignore [no-untyped-def]
    """Django magic function to obtain a dynamic success URL."""
    return reverse_lazy("main:funding_detail", kwargs={"pk": self.object.pk})

ProjectCreateView ¤

Bases: PermissionRequiredMixin, CreateView

View to create a new project.

ProjectDetailView ¤

Bases: PermissionRequiredMixin, CustomBaseDetailView

View to view details of a project.

Functions¤
get_context_data(**kwargs) ¤

Add project name and funding table to the context.

A custom query is used with the funding table, so only the funding for the current project is displayed.

Source code in main/views.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:  # type: ignore
    """Add project name and funding table to the context.

    A custom query is used with the funding table, so only the funding for the
    current project is displayed.
    """
    context = super().get_context_data(**kwargs)
    context["project_name"] = self.get_object().name
    # get funding info for the current project
    funding_source = self.get_object().funding_source.all()
    funding_table = tables.FundingTable(funding_source)
    project_phase = models.ProjectPhase.objects.filter(
        project__name=self.get_object().name
    )
    phase_table = tables.ProjectPhaseTable(project_phase)
    # enables the table to be sorted by column headings
    RequestConfig(self.request).configure(funding_table)
    RequestConfig(self.request).configure(phase_table)

    context["funding_table"] = funding_table
    context["phase_table"] = phase_table
    return context

ProjectPhaseCreateView ¤

Bases: PermissionRequiredMixin, CreateView

View to create a new project phase.

ProjectPhaseDeleteView ¤

Bases: PermissionRequiredMixin, DeleteView

Delete view based on a form from the Project Phase model.

ProjectPhaseDetailView ¤

Bases: PermissionRequiredMixin, CustomBaseDetailView

View to view details of a project.

Functions¤
get_context_data(**kwargs) ¤

Add project name and funding table to the context.

A custom query is used with the funding table, so only the funding for the current project is displayed.

Source code in main/views.py
277
278
279
280
281
282
283
284
285
286
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:  # type: ignore
    """Add project name and funding table to the context.

    A custom query is used with the funding table, so only the funding for the
    current project is displayed.
    """
    context = super().get_context_data(**kwargs)
    context["project_name"] = self.get_object().project.name

    return context

ProjectPhaseUpdateView ¤

Bases: PermissionRequiredMixin, UpdateView

Update view based on a form from the Project Phase model.

Functions¤
get_success_url() ¤

Django magic function to obtain a dynamic success URL.

Source code in main/views.py
322
323
324
325
326
327
def get_success_url(self):  # type: ignore [no-untyped-def]
    """Django magic function to obtain a dynamic success URL."""
    return reverse_lazy(
        "main:project_phase_detail",
        kwargs={"project_pk": self.object.project.pk, "pk": self.object.pk},
    )

ProjectUpdateView ¤

Bases: PermissionRequiredMixin, UpdateView

Update view based on a form from the Project model.

Functions¤
get_success_url() ¤

Django magic function to obtain a dynamic success URL.

Source code in main/views.py
252
253
254
def get_success_url(self):  # type: ignore [no-untyped-def]
    """Django magic function to obtain a dynamic success URL."""
    return reverse_lazy("main:project_detail", kwargs={"pk": self.object.pk})

ProjectsListView ¤

Bases: LoginRequiredMixin, FilterView

View to display the list of projects split in five pre-filtered tables.

Functions¤
get_context_data(**kwargs) ¤

Add multiple pre-filtered tables to the context.

Source code in main/views.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:  # type: ignore
    """Add multiple pre-filtered tables to the context."""
    context = super().get_context_data(**kwargs)

    base_qs = self.get_queryset()

    buckets = [
        ("Active", {"status": "Active"}, "active-"),
        ("Confirmed", {"status": "Confirmed"}, "confirmed-"),
        ("Tentative", {"status": "Tentative"}, "tentative-"),
        ("Finished", {"status": "Finished"}, "finished-"),
        ("Not done", {"status": "Not done"}, "not-done-"),
    ]

    created_tables: list[tuple[str, tables.ProjectTable]] = []
    for title, filt, prefix in buckets:
        qs = base_qs.filter(**filt)
        tbl = tables.ProjectTable(qs, prefix=prefix)
        RequestConfig(self.request).configure(tbl)
        created_tables.append((title, tbl))

    context["tables"] = created_tables
    return context

RegistrationView ¤

Bases: CreateView

View to register new users.

TODO: This is a placeholder for development. When SSO is implemented, this won't be needed since available users will be retrieved automatically.