Skip to content

views

main.views ¤

Init in views.

Classes¤

AboutPageView ¤

Bases: TemplateView

View that renders the about page.

AccountOverviewView ¤

Bases: TermsAcceptedMixin, RedirectView

Route users to the appropriate account page based on their skills.

Methods:¤
get_redirect_url(*args, **kwargs) ¤

Redirect to skill profile if skills exist, otherwise self-assess.

Source code in main/views/account_views.py
115
116
117
118
119
def get_redirect_url(self, *args: Any, **kwargs: Any) -> str:
    """Redirect to skill profile if skills exist, otherwise self-assess."""
    if UserSkill.objects.filter(user=self.request.user).exists():
        return reverse("skills_profile")
    return reverse("self_assess")

AuthenticatedHttpRequest ¤

Bases: HttpRequest

Custom HttpRequest type for authenticated users.

CompetencyDomain ¤

Bases: SluggedModel

Model for competency domains.

Classes¤
Meta ¤

Meta options for CompetencyDomain model.

EventsPageView ¤

Bases: TemplateView

View that renders the events page.

Methods:¤
get_context_data(**kwargs) ¤

Add events from CSV to the template context.

Source code in main/views/page_views.py
129
130
131
132
133
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: Mapping[str, Any]) -> dict[str, Any]:
    """Add events from CSV to the template context."""
    context = super().get_context_data(**kwargs)
    csv_path = Path("data/events.csv")
    events = []

    if csv_path.exists():
        with open(csv_path, newline="", encoding="utf-8") as csvfile:
            reader = csv.DictReader(csvfile)
            for row in reader:
                events.append(
                    {
                        "title": row.get("Title", ""),
                        "start_date": row.get("Start Date", ""),
                        "end_date": row.get("End Date", ""),
                        "description": row.get("Description", ""),
                        "contributors": row.get("Contributors", ""),
                        "image": static(
                            row.get("Image", "assets/img/blog/single/image.jpg")
                        ),
                    }
                )

    events.sort(key=lambda e: e["start_date"], reverse=True)

    context["events"] = events
    return context

FrameworkOverviewPageView ¤

Bases: TemplateView

View that renders an overview page for the framework.

FrameworkView ¤

Bases: View

A view that returns the core framework as a JSON string.

Methods:¤
get(request) ¤

Define the GET response.

Parameters:

Name Type Description Default
request HttpRequest

A GET request with no required parameters.

required

Returns:

Type Description
JsonResponse

A string of the full framework in JSON format. The top-level components are: - competency_domains: A list of the Competency Domains - competencies: A list of the Competencies - skills: A list of the Skills - skill_levels: A list of the Skill Levels

Source code in main/views/data_views.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def get(self, request: HttpRequest) -> JsonResponse:
    """Define the GET response.

    Args:
        request: A GET request with no required parameters.

    Returns:
        A string of the full framework in JSON format. The top-level components are:
            - competency_domains: A list of the Competency Domains
            - competencies: A list of the Competencies
            - skills: A list of the Skills
            - skill_levels: A list of the Skill Levels
    """
    return JsonResponse(export_framework(), json_dumps_params=dict(indent=2))

GetInvolvedPageView ¤

Bases: TemplateView

View that renders the get involved page.

GitHubMarkdownPageView ¤

Bases: TemplateView

Base view for pages that render markdown content fetched from GitHub.

Methods:¤
get_context_data(**kwargs) ¤

Add rendered markdown content and page metadata to the context.

Source code in main/views/page_views.py
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
def get_context_data(self, **kwargs: Mapping[str, Any]) -> dict[str, Any]:
    """Add rendered markdown content and page metadata to the context."""
    context = super().get_context_data(**kwargs)
    context["page_heading"] = self.page_heading

    try:
        context["markdown_content"] = mark_safe(
            nh3.clean(self.get_markdown_content())
        )
    except requests.RequestException:
        logger.exception("Failed to load markdown from %s", self.github_raw_url)
        context["markdown_content"] = mark_safe(
            f"<p>{self.unavailable_message}</p>"
        )

    return context
get_markdown_content() ¤

Fetch and convert remote markdown content to HTML.

Source code in main/views/page_views.py
266
267
268
269
270
271
272
273
274
275
276
277
def get_markdown_content(self) -> str:
    """Fetch and convert remote markdown content to HTML."""
    if not self.github_raw_url:
        raise ValueError("github_raw_url must be set on GitHubMarkdownPageView")

    response = requests.get(self.github_raw_url, timeout=5)
    response.raise_for_status()
    markdown_text = self._strip_duplicate_heading(response.text)
    return markdown.markdown(
        markdown_text,
        extensions=self.markdown_extensions,
    )

GovernancePageView ¤

Bases: GitHubMarkdownPageView

View that renders the governance page from GitHub Markdown.

IndexPageView ¤

Bases: TemplateView

View that renders the index/home page.

Methods:¤
get_context_data(**kwargs) ¤

Add skill levels and sample profile data to the template context.

Source code in main/views/page_views.py
56
57
58
59
60
61
62
63
64
65
66
67
68
def get_context_data(self, **kwargs: Mapping[str, Any]) -> dict[str, Any]:
    """Add skill levels and sample profile data to the template context."""
    context = super().get_context_data(**kwargs)
    logger.info("Rendering index page.")

    sample_data = _extract_and_combine_roles(
        ["main/static/assets/sample_data/sample_profile_1.json"]
    )
    context["chart_data"] = dumps(sample_data)
    context["skill_levels"] = dumps(
        list(SkillLevel.objects.values("level", "name"))
    )
    return context

LearningResource ¤

Bases: SluggedModel

Model for learning resources.

LearningResourceTable ¤

Bases: Table

Table class for the LearningResources model.

Classes¤
Meta ¤

Meta options for the LearningResourcesTable.

Methods:¤
render_language(value) ¤

Render the language field as a badge.

Source code in main/tables.py
53
54
55
56
57
def render_language(self, value: str) -> SafeString:
    """Render the language field as a badge."""
    return mark_safe(
        " ".join(format_html(badge_html, val.strip()) for val in value.split(","))
    )
render_name(value, record) ¤

Include the URL in the name.

Source code in main/tables.py
49
50
51
def render_name(self, value: str, record: LearningResource) -> SafeString:
    """Include the URL in the name."""
    return format_html(external_link_html, record.url, "fs-lg", value)
render_provider(value, record) ¤

Include the URL in the provider name.

Source code in main/tables.py
59
60
61
62
63
64
def render_provider(self, value: str, record: LearningResource) -> SafeString:
    """Include the URL in the provider name."""
    if record.provider is None or not record.provider.url:
        return mark_safe(value)

    return format_html(external_link_html, record.provider.url, "", value)
render_skill_set(value) ¤

Include the relevant skills as button links.

Source code in main/tables.py
66
67
68
def render_skill_set(self, value: "ManyRelatedManager[Skill]") -> SafeString:
    """Include the relevant skills as button links."""
    return _render_skills(value.all())

LearningResourcesPageView ¤

Bases: SingleTableView

View that renders the page with all learning resources.

LicensingPageView ¤

Bases: GitHubMarkdownPageView

View that renders the licensing page from GitHub Markdown.

PrivacyPageView ¤

Bases: TemplateView

View that renders the privacy page.

RolesPageView ¤

Bases: TemplateView

View that renders the role profiles page.

Methods:¤
get_context_data(**kwargs) ¤

Add sample profile data to the template context.

Source code in main/views/page_views.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
def get_context_data(self, **kwargs: Mapping[str, Any]) -> dict[str, Any]:
    """Add sample profile data to the template context."""
    context = super().get_context_data(**kwargs)

    sample_data = _extract_and_combine_roles(
        [
            "main/static/assets/sample_data/sample_profile_1.json",
            "main/static/assets/sample_data/sample_profile_41.json",
            "main/static/assets/sample_data/sample_profile_59.json",
        ]
    )
    context["chart_data"] = sample_data
    context["skill_levels"] = dumps(
        list(SkillLevel.objects.values("level", "name"))
    )
    return context

SelfAssessPageView ¤

Bases: TermsAcceptedMixin, FormView[UserSkillsForm]

View that renders the self-assessment questionnaire page.

Methods:¤
form_valid(form) ¤

Handle valid form submission.

Source code in main/views/account_views.py
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
def form_valid(self, form: UserSkillsForm) -> HttpResponse:
    """Handle valid form submission."""
    created_skills, updated_skills = form.save(self.request.user)

    # Add success messages
    if created_skills:
        messages.success(
            self.request,
            f"Successfully created {len(created_skills)} new skill assessments.",
        )
    if updated_skills:
        messages.success(
            self.request,
            f"Successfully updated {len(updated_skills)} "
            f"existing skill assessments.",
        )

    return super().form_valid(form)
get_form_kwargs() ¤

Return the keyword arguments for instantiating the form.

Source code in main/views/account_views.py
144
145
146
147
148
def get_form_kwargs(self) -> dict[str, Any]:
    """Return the keyword arguments for instantiating the form."""
    kwargs = super().get_form_kwargs()
    kwargs["user"] = self.request.user
    return kwargs

Skill ¤

Bases: SluggedModel

Model for skills.

Classes¤
Meta ¤

Meta options for Skill model.

Methods:¤
__str__() ¤

Return the name of the skill and the competency.

Source code in main/models/framework_models.py
155
156
157
def __str__(self) -> str:
    """Return the name of the skill and the competency."""
    return self.name + " (" + self.competency.name + ")"

SkillLevel ¤

Bases: NamedModel

Model for skill levels.

SkillLevelsPageView ¤

Bases: TemplateView

View that renders the skill levels page.

Methods:¤
get_context_data(**kwargs) ¤

Add skill levels to the template context.

Source code in main/views/page_views.py
94
95
96
97
98
99
def get_context_data(self, **kwargs: Mapping[str, Any]) -> dict[str, Any]:
    """Add skill levels to the template context."""
    context = super().get_context_data(**kwargs)
    skill_levels = SkillLevel.objects.all().order_by("level")
    context["skill_levels"] = skill_levels
    return context

SkillPageView ¤

Bases: TemplateView

View that renders a single skill page.

Methods:¤
get_context_data(**kwargs) ¤

Add the selected skill and related data to the template context.

Source code in main/views/page_views.py
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
def get_context_data(self, **kwargs: Mapping[str, Any]) -> dict[str, Any]:
    """Add the selected skill and related data to the template context."""
    context = super().get_context_data(**kwargs)

    slug = self.kwargs["slug"]
    skill = get_object_or_404(
        Skill.objects.select_related(
            "competency",
            "competency__competency_domain",
        ).prefetch_related(
            "related_skills",
            "learning_resources__provider",
            "tools",
        ),
        slug=slug,
    )

    tools_qs = skill.tools.all().order_by("name")
    context["skill"] = skill
    context["related_skills"] = skill.related_skills.all().order_by("name")
    context["learning_resources"] = skill.learning_resources.all().order_by("name")
    context["tools"] = tools_qs.filter(kind=ToolLanguageMethodology.Kind.TOOL)
    context["languages"] = tools_qs.filter(
        kind=ToolLanguageMethodology.Kind.LANGUAGE
    )
    context["methodologies"] = tools_qs.filter(
        kind=ToolLanguageMethodology.Kind.METHODOLOGY
    )

    return context

SkillProfileView ¤

Bases: TermsAcceptedMixin, TemplateView

View that renders the skill profile page.

Methods:¤
get_context_data(**kwargs) ¤

Add user skills and skill levels to the template context.

Source code in main/views/account_views.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
    """Add user skills and skill levels to the template context."""
    context = super().get_context_data(**kwargs)
    logger.info("Rendering skills-profile page.")

    user_skills = UserSkill.objects.filter(user=self.request.user.pk)
    user_skills_data = [
        {
            "skill": user_skill.skill.name,
            "category": user_skill.skill.competency.competency_domain.name,
            "subcategory": user_skill.skill.competency.name,
            "skill_level": user_skill.skill_level.level,
        }
        for user_skill in user_skills
    ]

    context["chart_data"] = dumps(
        [
            {
                "user_id": "root",
                "user_data": user_skills_data,
            }
        ]
    )
    context["skill_levels"] = dumps(
        list(SkillLevel.objects.values("level", "name"))
    )
    return context

SkillsAndCompetenciesPageView ¤

Bases: TemplateView

View that renders the competencies page.

Methods:¤
get_context_data(**kwargs) ¤

Add the competencies framework data to the template context.

Source code in main/views/page_views.py
186
187
188
189
190
191
192
193
194
195
def get_context_data(self, **kwargs: Mapping[str, Any]) -> dict[str, Any]:
    """Add the competencies framework data to the template context."""
    context = super().get_context_data(**kwargs)

    domains = CompetencyDomain.objects.prefetch_related(
        "competency_set__skill_set"
    ).all()

    context["domains"] = domains
    return context

TermsAcceptanceForm(*args, **kwargs) ¤

Bases: Form

Simple form that requires terms acceptance for existing users.

Include links to terms and privacy pages in the checkbox label.

Source code in main/forms.py
70
71
72
73
def __init__(self, *args: Any, **kwargs: Any) -> None:
    """Include links to terms and privacy pages in the checkbox label."""
    super().__init__(*args, **kwargs)
    self.fields["tos"].label = _(_build_tos_form_label())
Methods:¤

TermsAcceptanceView ¤

Bases: LoginRequiredMixin, FormView[TermsAcceptanceForm]

Prompt authenticated users to accept terms before continuing.

Methods:¤
form_valid(form) ¤

Persist acceptance and the acceptance timestamp.

Source code in main/views/account_views.py
65
66
67
68
69
70
71
def form_valid(self, form: TermsAcceptanceForm) -> HttpResponse:
    """Persist acceptance and the acceptance timestamp."""
    user = cast("UserType", self.request.user)
    user.agreed_to_tos = form.cleaned_data["tos"]
    user.date_agreed = timezone.now()
    user.save(update_fields=["agreed_to_tos", "date_agreed"])
    return HttpResponseRedirect(str(self.success_url))

TermsAcceptedMixin ¤

Bases: LoginRequiredMixin

Require authenticated users to accept terms before accessing account pages.

Methods:¤
dispatch(request, *args, **kwargs) ¤

Redirect to terms acceptance page when the user has not accepted terms.

Source code in main/views/account_views.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
def dispatch(
    self, request: HttpRequest, *args: Any, **kwargs: Any
) -> HttpResponseBase:
    """Redirect to terms acceptance page when the user has not accepted terms."""
    if not request.user.is_authenticated:
        return self.handle_no_permission()

    if request.user.agreed_to_tos:
        return super().dispatch(request, *args, **kwargs)

    resolver_match = request.resolver_match
    if resolver_match and resolver_match.url_name == self.terms_acceptance_url_name:
        return super().dispatch(request, *args, **kwargs)

    return HttpResponseRedirect(reverse(self.terms_acceptance_url_name))

TermsPageView ¤

Bases: TemplateView

View that renders the terms and conditions page.

ToolLanguageMethodology ¤

Bases: SluggedModel

Model for tools, languages and methodologies.

Classes¤
Kind ¤

Bases: TextChoices

Enumeration of Kind choices.

Meta ¤

Meta options for Tool model.

ToolLanguageMethodologyTable ¤

Bases: Table

Table class for the ToolLanguageMethodology model.

Classes¤
Meta ¤

Meta options for the ToolLanguageMethodologyTable.

Methods:¤
render_kind(value) ¤

Render the kind field as a badge.

Source code in main/tables.py
87
88
89
def render_kind(self, value: str) -> SafeString:
    """Render the kind field as a badge."""
    return format_html(badge_html, value)
render_name(value, record) ¤

Include the URL in the name.

Source code in main/tables.py
83
84
85
def render_name(self, value: str, record: ToolLanguageMethodology) -> SafeString:
    """Include the URL in the name."""
    return format_html(external_link_html, record.url, "fs-lg", value)
render_skill_set(value) ¤

Include the relevant skills as button links.

Source code in main/tables.py
91
92
93
def render_skill_set(self, value: "ManyRelatedManager[Skill]") -> SafeString:
    """Include the relevant skills as button links."""
    return _render_skills(value.all())

ToolsLanguagesMethodologiesPageView ¤

Bases: SingleTableView

View that renders the page with all tools, languages and methodologies.

UserSkill ¤

Bases: Model

Model for mapping users to skills and skill levels.

Classes¤
Meta ¤

Meta options for UserSkill model.

UserSkillsForm(*args, user, **kwargs) ¤

Bases: Form

Form for creating UserSkills for all skills in the database.

Initialize the form with a field for each skill.

Source code in main/forms.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
def __init__(self, *args: Any, user: "UserType", **kwargs: Any) -> None:
    """Initialize the form with a field for each skill."""
    self.user = user
    super().__init__(*args, **kwargs)

    # Get all skills, ordered by competency for better organization
    skills = Skill.objects.select_related(
        "competency", "competency__competency_domain"
    ).order_by("competency__competency_domain__name", "competency__name", "name")

    # Get all skill levels for the choice field
    skill_levels = SkillLevel.objects.all().order_by("level")
    skill_level_choices = [
        (level.id, f"{level.level} - {level.name}") for level in skill_levels
    ]

    # Store skill organization data for layout building
    skill_organization: dict[str, dict[str, list[Skill]]] = {}

    # Create a field for each skill
    for skill in skills:
        field_name = f"skill_{skill.id}"

        # Check if user already has this skill
        existing_user_skill = None
        if self.user:
            try:
                existing_user_skill = UserSkill.objects.get(
                    user=self.user, skill=skill
                )
            except UserSkill.DoesNotExist:
                pass

        # Set initial value if user already has this skill
        initial_value = (
            existing_user_skill.skill_level.id if existing_user_skill else None
        )

        # Organize skills by competency hierarchy for layout
        parent_name = (
            skill.competency.competency_domain.name
            if skill.competency.competency_domain
            else "No Parent"
        )

        if parent_name not in skill_organization:
            skill_organization[parent_name] = {}

        if skill.competency.name not in skill_organization[parent_name]:
            skill_organization[parent_name][skill.competency.name] = []

        skill_organization[parent_name][skill.competency.name].append(skill)

        # Create form field with just the skill name as label
        self.fields[field_name] = forms.ChoiceField(
            choices=[("", "--- Select Level ---"), *skill_level_choices],
            required=False,
            initial=initial_value,
            label="Skill Level",
            widget=forms.Select(attrs={"class": "form-select form-select-sm"}),
        )

    # Set up crispy forms helper
    self.helper = FormHelper()
    self.helper.form_method = "post"

    # Build the layout structure
    layout_elements = []

    for competency_domain, competencies in skill_organization.items():
        # Add parent competency heading
        parent_heading = (
            f'<h2 class="card-title text-primary mt-5">{competency_domain}</h2>'
        )
        parent_div = Div(HTML(parent_heading), css_class="mb-5")

        competency_elements = []
        for competency, skills_list in competencies.items():
            # Add competency heading
            competency_heading = f"<h4>{competency}</h4>"

            # Outer card div
            competency_div = Div(css_class="mt-5 card rounded-1")

            # Card body div with heading and table
            card_body_div = Div(css_class="card-body")

            # Add competency heading inside card body
            card_body_div.append(HTML(competency_heading))

            # Build the table for skills
            table_html = """
            <table class="table mt-2">
                <thead>
                    <tr>
                        <th scope="col">Skill</th>
                        <th scope="col">Description</th>
                        <th scope="col">Your Level</th>
                    </tr>
                </thead>
                <tbody>
            """
            for skill in skills_list:
                table_html += f"""
                    <tr>
                        <td class="fw-semibold">{skill.name}</td>
                        <td>{skill.description}</td>
                        <td>{{{{ form.skill_{skill.id} }}}}</td>
                    </tr>
                """
            table_html += """
                </tbody>
            </table>
            """

            # Append table to card body
            card_body_div.append(HTML(table_html))

            # Add a submit button for this competency
            competency_submit = Div(
                Submit(
                    f"submit_{competency.replace(' ', '_')}",
                    "Save",
                    css_class="btn btn-primary mt-3",
                ),
                css_class="mt-3",
            )
            card_body_div.append(competency_submit)

            # Append card body to the card
            competency_div.append(card_body_div)

            # Add the competency div to elements
            competency_elements.append(competency_div)

        parent_div.extend(competency_elements)

        layout_elements.append(parent_div)

    # Add submit button
    cancel_link = (
        "<a href=\"{% url 'profile' %}\" "
        'class="btn btn-secondary btn-lg ms-2">Cancel</a>'
    )
    layout_elements.append(
        Div(
            Submit(
                "submit",
                "Save All Skill Assessments",
                css_class="btn btn-primary btn-lg",
            ),
            HTML(cancel_link),
            css_class="mt-4 pt-3 border-top",
        )
    )

    self.helper.layout = Layout(*layout_elements)
Methods:¤
save(user) ¤

Save the form data as UserSkill instances.

Source code in main/forms.py
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
def save(self, user: "UserType") -> tuple[list[UserSkill], list[UserSkill]]:
    """Save the form data as UserSkill instances."""
    created_skills = []
    updated_skills = []

    for field_name, skill_level_id in self.cleaned_data.items():
        if field_name.startswith("skill_") and skill_level_id:
            skill_id = int(field_name.replace("skill_", ""))
            skill = Skill.objects.get(id=skill_id)
            skill_level = SkillLevel.objects.get(id=skill_level_id)

            # Check if UserSkill already exists
            user_skill, created = UserSkill.objects.get_or_create(
                user=user, skill=skill, defaults={"skill_level": skill_level}
            )

            if not created:
                # Update existing UserSkill
                user_skill.skill_level = skill_level
                user_skill.save()
                updated_skills.append(user_skill)
            else:
                created_skills.append(user_skill)

    return created_skills, updated_skills

UserUpdateView ¤

Bases: TermsAcceptedMixin, UpdateView['UserType', ModelForm['UserType']]

View that renders the user update form page.

Methods:¤
get_object(queryset=None) ¤

Remove the need for url args by returning the current user.

Source code in main/views/account_views.py
131
132
133
def get_object(self, queryset: Any | None = None) -> "UserType":
    """Remove the need for url args by returning the current user."""
    return self.request.user

ViewSkillProfilePageView ¤

Bases: TemplateView

View that renders a shared skill profile based on query parameters.

Methods:¤
get_context_data(**kwargs) ¤

Add skill profile data from query parameters to the context.

Source code in main/views/page_views.py
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
def get_context_data(self, **kwargs: Mapping[str, Any]) -> dict[str, Any]:
    """Add skill profile data from query parameters to the context."""
    context = super().get_context_data(**kwargs)

    chart_data_json = nh3.clean(self.request.GET.get("chart_data", "[]"))
    skill_levels_json = nh3.clean(self.request.GET.get("skill_levels", "[]"))

    try:
        context["chart_data"] = json.loads(chart_data_json)
        context["skill_levels"] = json.loads(skill_levels_json)
    except json.JSONDecodeError:
        context["chart_data"] = []
        context["skill_levels"] = []
        context["error_message"] = "Invalid data provided in query parameters."

    return context

Functions:¤

export_framework() ¤

Exports the core framework into one dictionary with each model as a key.

Returns:

Type Description
dict[str, list[dict[str, str]]]

A dictionary containing the entire framework. Each model is labelled by a key and is a list of dictionaries. This is JSON compatible.

Source code in main/io_resources.py
262
263
264
265
266
267
268
269
270
271
272
273
274
def export_framework() -> dict[str, list[dict[str, str]]]:
    """Exports the core framework into one dictionary with each model as a key.

    Returns:
        A dictionary containing the entire framework. Each model is labelled by a key
            and is a list of dictionaries. This is JSON compatible.
    """
    return dict(
        competency_domains=CompetencyDomainResource().export().dict,
        competencies=CompetencyResource().export().dict,
        skills=SkillResource().export().dict,
        skill_levels=SkillLevelResource().export().dict,
    )