Skip to content

Setup mentorship app and added models #1644

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 50 commits into from
Jun 25, 2025
Merged

Conversation

Rajgupta36
Copy link
Collaborator

Resolves #1578

Tasks -

  • Created new app: mentorship
  • Created Models Mentor,Mentee,Program,Module
  • Model testing to be done

Rajgupta36 and others added 30 commits June 4, 2025 19:24
* implemented authentication using next-auth

* update code

* type fix

* updated migration

* added backend test cases

* added frontend unit test cases

* added e2e test case

* pre-commit

* fixes e2e test cases

* updated ci/cd

* updated code

* upgraded mutaitons from graphene to strawberry

* updated code

* Update code

* Update tests

* fixes

* fix test

* added relation

* Update code

* Update pnpm-lock.yaml

---------

Co-authored-by: Kate Golovanova <[email protected]>
Co-authored-by: Arkadii Yakovets <[email protected]>
Co-authored-by: Arkadii Yakovets <[email protected]>
…WASP#1556)

Bumps python from 3.13.3-alpine to 3.13.4-alpine.

---
updated-dependencies:
- dependency-name: python
  dependency-version: 3.13.4-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ASP#1557)

Bumps python from 3.13.3-alpine to 3.13.4-alpine.

---
updated-dependencies:
- dependency-name: python
  dependency-version: 3.13.4-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…P#1559)

Bumps python from 3.13.3-alpine to 3.13.4-alpine.

---
updated-dependencies:
- dependency-name: python
  dependency-version: 3.13.4-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Update CONTRIBUTING.md

* Update CONTRIBUTING.md

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
* Add test coverage for csrf.py

Signed-off-by: bandhan-majumder <[email protected]>

* Update code

---------

Signed-off-by: bandhan-majumder <[email protected]>
Co-authored-by: Arkadii Yakovets <[email protected]>
* handle empty auth credentials

* update test cases

* upgrade code

* update code

* remove check route

* fix test case

* fixes and update usermenu

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
* fix route

* format fix

* introduce flag for auth

* update env

* changed default value

* fix test cases

* fix e2 test cases

* Add dynamic variable for isAuthEnabled

* Clean up

* Clean up and fix tests

* Update code

* Fix code quality issues

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Co-authored-by: Kate <[email protected]>
Co-authored-by: Arkadii Yakovets <[email protected]>
* Add project_health_metrics node and query

* Add health field to the ProjectNode that represents sll ProjectHealthMetrics objects of the project

* Add tests

* Update filtering and add fields to models

* Update filtering

* Update tests

* Save new boolean values

* Add boolean mapping

* Add query tests

* Merge migrations

* Update filtering, add migrations, and update scripts

* Update tests and queries

* Add test with filters

* Update filtering

* Update tests

* Merge migrations

* Revert unnecessary work and apply suggestions

* Remove has_no_recent_commits from project

* Add missing fields for FE query

* Remove project name from the test

* Clean migrations

* Update code

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Copy link

Please retry analysis of this Pull-Request directly on SonarQube Cloud

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend/apps/mentorship/models/programmodule.py (1)

55-57: Consider defensive programming in str method.

Similar to the save method, the __str__ method could benefit from null checks to prevent potential AttributeErrors during object creation or edge cases.

Apply this defensive improvement:

    def __str__(self) -> str:
        """Return a readable identifier for the Program-Module link."""
-        return f"{self.module.name or 'Unnamed Module'} in {self.program.name}"
+        module_name = self.module.name if self.module else "Unlinked Module"
+        program_name = self.program.name if self.program else "Unlinked Program"
+        return f"{module_name or 'Unnamed Module'} in {program_name}"
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 83a52e5 and 09a2886.

⛔ Files ignored due to path filters (3)
  • backend/poetry.lock is excluded by !**/*.lock
  • docs/poetry.lock is excluded by !**/*.lock
  • frontend/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • backend/apps/mentorship/admin.py (1 hunks)
  • backend/apps/mentorship/migrations/0001_initial.py (1 hunks)
  • backend/apps/mentorship/models/mentor.py (1 hunks)
  • backend/apps/mentorship/models/programmodule.py (1 hunks)
🧰 Additional context used
🪛 Pylint (3.3.7)
backend/apps/mentorship/admin.py

[refactor] 13-13: Too few public methods (0/2)

(R0903)


[refactor] 21-21: Too few public methods (0/2)

(R0903)


[refactor] 32-32: Too few public methods (0/2)

(R0903)


[refactor] 47-47: Too few public methods (0/2)

(R0903)


[refactor] 63-63: Too few public methods (0/2)

(R0903)


[refactor] 88-88: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/migrations/0001_initial.py

[refactor] 7-7: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/models/mentor.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/programmodule.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
🔇 Additional comments (3)
backend/apps/mentorship/models/mentor.py (1)

11-43: LGTM! Model implementation is well-structured.

The Mentor model is properly implemented with appropriate field types, relationships, and metadata. The null check in the __str__ method correctly handles the edge case where user might be None.

backend/apps/mentorship/admin.py (1)

1-110: Excellent Django admin configuration.

The admin classes are comprehensively configured with appropriate display fields, search capabilities, and filtering options. The previous suggestion to improve EnrollmentAdmin has been properly implemented, and all models are correctly registered.

backend/apps/mentorship/migrations/0001_initial.py (1)

1-365: Well-structured initial migration.

The migration properly defines the complete database schema for the mentorship app with all necessary models, relationships, and constraints. The structure follows Django migration best practices and creates a solid foundation for the mentorship functionality.

@arkid15r
Copy link
Collaborator

I updated the schema and going to take another look on it tomorrow -- maybe we could simplify it a bit. Curious to hear your thoughts @kasya @Rajgupta36

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (7)
backend/apps/mentorship/models/common/experience_level.py (1)

6-7: Fix the incorrect docstring.

The docstring says "Matching attributes model" but this is the ExperienceLevel model.

-    """Matching attributes model."""
+    """Experience level model."""
backend/apps/mentorship/models/mentor_module.py (1)

1-1: Fix the incorrect file header docstring.

The file header says "ProgramModule model" but this file contains the MentorModule model.

-"""ProgramModule model for the Mentorship app."""
+"""MentorModule model for the Mentorship app."""
backend/apps/mentorship/models/program_module.py (1)

42-49: Improve the default value assignment logic.

The current logic using or might not work correctly if dates are explicitly set to None. Consider using more explicit checks.

     def save(self, *args, **kwargs):
         """Save program module."""
         if self.program:
             # Set default dates from program if not provided.
-            self.start_date = self.start_date or self.program.start_date
-            self.end_date = self.end_date or self.program.end_date
+            if self.start_date is None:
+                self.start_date = self.program.start_date
+            if self.end_date is None:
+                self.end_date = self.program.end_date

         super().save(*args, **kwargs)
backend/apps/mentorship/models/module.py (1)

38-45: Consider fallback value in __str__ method for better representation.

The name field allows blank=True with default="", but the __str__ method returns self.name which could be an empty string. This may result in confusing representations in the Django admin or other interfaces.

Consider adding a fallback:

    def __str__(self) -> str:
        """Return a human-readable representation of the module.

        Returns:
            str: The module name or associated project.

        """
-        return self.name
+        return self.name or f"Module for {self.project}"
backend/apps/mentorship/models/mentee_program.py (1)

32-39: Fix docstring inconsistency in __str__ method.

The docstring mentions "Mentee and program with level" but the actual return statement only includes mentee and program without level information.

    def __str__(self) -> str:
        """Return a human-readable representation of the enrollment.

        Returns:
-            str: Mentee and program with level.
+            str: Mentee and program.

        """
        return f"{self.mentee} - {self.program}"
backend/apps/mentorship/models/mentee_module.py (2)

11-12: Fix class docstring to accurately reflect module enrollment.

The class docstring says "Mentee program enrollment" but this model represents mentee enrollment in modules, not programs.

-    """Mentee program enrollment."""
+    """Mentee module enrollment."""

32-39: Fix method docstring to reference module instead of program.

The docstring mentions "program" but this method deals with mentee-module relationships.

    def __str__(self) -> str:
        """Return a human-readable representation of the enrollment.

        Returns:
-            str: Mentee and program with level.
+            str: Mentee and module.

        """
        return f"{self.mentee} - {self.module}"
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 09a2886 and 49815c9.

📒 Files selected for processing (14)
  • backend/apps/mentorship/admin.py (1 hunks)
  • backend/apps/mentorship/migrations/0001_initial.py (1 hunks)
  • backend/apps/mentorship/models/__init__.py (1 hunks)
  • backend/apps/mentorship/models/common/__init__.py (1 hunks)
  • backend/apps/mentorship/models/common/experience_level.py (1 hunks)
  • backend/apps/mentorship/models/common/matching_attributes.py (1 hunks)
  • backend/apps/mentorship/models/mentee.py (1 hunks)
  • backend/apps/mentorship/models/mentee_module.py (1 hunks)
  • backend/apps/mentorship/models/mentee_program.py (1 hunks)
  • backend/apps/mentorship/models/mentor.py (1 hunks)
  • backend/apps/mentorship/models/mentor_module.py (1 hunks)
  • backend/apps/mentorship/models/module.py (1 hunks)
  • backend/apps/mentorship/models/program.py (1 hunks)
  • backend/apps/mentorship/models/program_module.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • backend/apps/mentorship/models/common/init.py
🧰 Additional context used
🪛 Pylint (3.3.7)
backend/apps/mentorship/models/mentor_module.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/common/matching_attributes.py

[refactor] 9-9: Too few public methods (0/2)

(R0903)


[refactor] 6-6: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/models/common/experience_level.py

[refactor] 9-9: Too few public methods (0/2)

(R0903)


[refactor] 12-12: Too few public methods (0/2)

(R0903)


[refactor] 6-6: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/models/program.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 18-18: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/program_module.py

[refactor] 11-11: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/models/mentee_program.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/mentee_module.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/mentor.py

[refactor] 15-15: Too few public methods (0/2)

(R0903)


[refactor] 12-12: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/mentee.py

[refactor] 15-15: Too few public methods (0/2)

(R0903)


[refactor] 12-12: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/migrations/0001_initial.py

[refactor] 8-8: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/admin.py

[refactor] 13-13: Too few public methods (0/2)

(R0903)


[refactor] 25-25: Too few public methods (0/2)

(R0903)


[refactor] 36-36: Too few public methods (0/2)

(R0903)


[refactor] 50-50: Too few public methods (0/2)

(R0903)


[refactor] 64-64: Too few public methods (0/2)

(R0903)


[refactor] 89-89: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/models/module.py

[refactor] 13-13: Too few public methods (0/2)

(R0903)


[refactor] 10-10: Too few public methods (1/2)

(R0903)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (11)
backend/apps/mentorship/models/common/matching_attributes.py (1)

6-24: LGTM! Well-structured abstract model for matching attributes.

The implementation correctly uses JSONField for flexible domain and tag storage, with appropriate defaults and help text. The abstract base class pattern is well-suited for this shared functionality.

backend/apps/mentorship/models/common/experience_level.py (1)

12-25: Good use of TextChoices for experience levels.

The implementation correctly uses Django's TextChoices for type-safe experience level management. The max_length of 12 is appropriate for the longest choice ("intermediate").

backend/apps/mentorship/models/__init__.py (1)

1-7: Clean model imports structure.

The consolidated imports follow Django best practices and will enable clean imports throughout the application.

backend/apps/mentorship/models/mentor_module.py (1)

11-35: Well-structured intermediary model.

The model correctly implements the many-to-many relationship between mentors and modules with appropriate constraints and inheritance from common abstract models.

backend/apps/mentorship/models/program_module.py (1)

30-34: Consider the implications of OneToOneField constraint.

Using OneToOneField means each module can only belong to one program. This might be too restrictive if modules are intended to be reusable across multiple programs.

Please verify whether modules should be limited to a single program or if they should be reusable across multiple programs. If reusable, consider changing to ForeignKey.

backend/apps/mentorship/models/program.py (1)

38-42: LGTM! Good field design for program identification.

The name field is properly configured as unique and required, ensuring each program has a distinct identifier.

backend/apps/mentorship/models/mentee_program.py (1)

14-17: LGTM! Proper unique constraint prevents duplicate enrollments.

The unique_together constraint on ("mentee", "program") correctly prevents a mentee from enrolling in the same program multiple times.

backend/apps/mentorship/models/mentor.py (1)

35-42: LGTM! Excellent null-safe implementation.

The __str__ method properly handles the case where user might be None, preventing potential AttributeError exceptions. The fallback "Unlinked Mentor" provides clear indication of the state.

backend/apps/mentorship/models/mentee.py (1)

36-43: To determine the correct attribute, let’s inspect how the user field is defined in the Mentee model and see whether it points to a GitHub user or the Django user:

#!/bin/bash
# Show the Mentee model, including its user field
sed -n '1,200p' backend/apps/mentorship/models/mentee.py
grep -n "user =" backend/apps/mentorship/models/mentee.py

This will confirm which model and field we should reference in __str__.

backend/apps/mentorship/admin.py (1)

44-47: Verify JSONField search functionality.

Searching directly on JSONField "domains" might not work as expected in Django admin. JSONField searches typically require specific query syntax or custom search methods.

Consider testing the search functionality or using a custom search method if needed.

#!/bin/bash
# Check if there are any custom search methods or JSONField handling in the codebase
rg -A 5 "JSONField.*search" --type py
rg -A 5 "domains.*search" --type py
backend/apps/mentorship/migrations/0001_initial.py (1)

8-450: Well-structured initial migration.

The migration properly creates all necessary tables, relationships, and constraints for the mentorship domain. The schema design supports flexible mentorship programs with proper many-to-many relationships through intermediary models.

Copy link
Collaborator

@kasya kasya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just one request ⬇️

@github-actions github-actions bot removed the frontend label Jun 24, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (3)
backend/apps/mentorship/models/mentor_module.py (1)

28-32: Fix the incorrect verbose_name for the mentor field.

The verbose_name says "Program" but this is the mentor field.

Apply this diff:

-        verbose_name="Program",
+        verbose_name="Mentor",
backend/apps/mentorship/models/program.py (1)

12-74: Consider adding date validation as previously suggested.

The model inherits from StartEndRange which provides date fields, but lacks validation to ensure logical date ordering. This was mentioned in previous reviews.

Consider adding a clean() method to validate date constraints:

+    def clean(self):
+        """Validate the program data."""
+        super().clean()
+        if hasattr(self, 'started_at') and hasattr(self, 'ended_at'):
+            if self.started_at and self.ended_at and self.started_at >= self.ended_at:
+                from django.core.exceptions import ValidationError
+                raise ValidationError("End date must be after start date.")
backend/apps/mentorship/migrations/0001_initial.py (1)

64-64: Fix incorrect verbose_name for mentor field.

The mentor field has verbose_name="Program" but should be verbose_name="Mentor" since it references a mentor, not a program.

-                ('mentor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mentorship.mentor', verbose_name='Program')),
+                ('mentor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mentorship.mentor', verbose_name='Mentor')),
🧹 Nitpick comments (7)
backend/apps/mentorship/models/common/start_end_range.py (1)

12-13: Consider reordering fields and adding validation.

The field ordering is unconventional - typically started_at should come before ended_at. Also consider adding validation to ensure the start date is not after the end date.

Apply this diff to improve the field ordering and add validation:

-    ended_at = models.DateTimeField(verbose_name="End date and time")
-    started_at = models.DateTimeField(verbose_name="Start date and time")
+    started_at = models.DateTimeField(verbose_name="Start date and time")
+    ended_at = models.DateTimeField(verbose_name="End date and time")
+
+    def clean(self):
+        """Validate that start date is not after end date."""
+        super().clean()
+        if self.started_at and self.ended_at and self.started_at > self.ended_at:
+            raise ValidationError("Start date cannot be after end date")

You'll also need to add the import:

+from django.core.exceptions import ValidationError
backend/apps/mentorship/models/mentor_module.py (2)

1-1: Fix the incorrect docstring.

The docstring refers to "ProgramModule model" but this is the MentorModule model.

Apply this diff:

-"""ProgramModule model for the Mentorship app."""
+"""MentorModule model for the Mentorship app."""

27-27: Improve the comment description.

The comment "# FKs." is not very descriptive. Consider using a more meaningful comment.

Apply this diff:

-    # FKs.
+    # Foreign key relationships.
backend/apps/mentorship/models/mentee_module.py (1)

32-39: Fix the docstring reference.

The docstring mentions "program" but this model is for mentee-module enrollment, not program enrollment.

    def __str__(self) -> str:
        """Return a human-readable representation of the enrollment.

        Returns:
-            str: Mentee and program with level.
+            str: Mentee and module enrollment.

        """
        return f"{self.mentee} - {self.module}"
backend/apps/mentorship/models/module.py (2)

46-53: Remove redundant null=True from ManyToManyField.

ManyToManyField cannot be null, so null=True is redundant and should be removed.

    mentors = models.ManyToManyField(
        "mentorship.Mentor",
        verbose_name="Mentors",
        related_name="modules",
        through="mentorship.MentorModule",
        blank=True,
-        null=True,
    )

24-29: Consider making name field required.

Allowing blank module names might lead to confusing or hard-to-identify modules. Consider making this field required.

    name = models.CharField(
        max_length=200,
        verbose_name="Name",
-        blank=True,
-        default="",
    )
backend/apps/mentorship/migrations/0001_initial.py (1)

85-85: Consider removing null=True for ManyToManyField.

ManyToManyFields don't support null=True as they don't store data in the model's table. Django will ignore this parameter, but it's misleading.

-                ('mentors', models.ManyToManyField(blank=True, null=True, related_name='modules', through='mentorship.MentorModule', to='mentorship.mentor', verbose_name='Mentors')),
+                ('mentors', models.ManyToManyField(blank=True, related_name='modules', through='mentorship.MentorModule', to='mentorship.mentor', verbose_name='Mentors')),
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 49815c9 and 9c7b9a3.

📒 Files selected for processing (12)
  • backend/apps/mentorship/admin.py (1 hunks)
  • backend/apps/mentorship/migrations/0001_initial.py (1 hunks)
  • backend/apps/mentorship/models/__init__.py (1 hunks)
  • backend/apps/mentorship/models/common/__init__.py (1 hunks)
  • backend/apps/mentorship/models/common/start_end_range.py (1 hunks)
  • backend/apps/mentorship/models/mentee.py (1 hunks)
  • backend/apps/mentorship/models/mentee_module.py (1 hunks)
  • backend/apps/mentorship/models/mentee_program.py (1 hunks)
  • backend/apps/mentorship/models/mentor.py (1 hunks)
  • backend/apps/mentorship/models/mentor_module.py (1 hunks)
  • backend/apps/mentorship/models/module.py (1 hunks)
  • backend/apps/mentorship/models/program.py (1 hunks)
🧰 Additional context used
🪛 Pylint (3.3.7)
backend/apps/mentorship/models/mentor.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/mentor_module.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/mentee_module.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/program.py

[refactor] 15-15: Too few public methods (0/2)

(R0903)


[refactor] 19-19: Too few public methods (0/2)

(R0903)


[refactor] 12-12: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/module.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/migrations/0001_initial.py

[refactor] 9-9: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/admin.py

[refactor] 12-12: Too few public methods (0/2)

(R0903)


[refactor] 24-24: Too few public methods (0/2)

(R0903)


[refactor] 35-35: Too few public methods (0/2)

(R0903)


[refactor] 49-49: Too few public methods (0/2)

(R0903)


[refactor] 63-63: Too few public methods (0/2)

(R0903)


[refactor] 88-88: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/models/common/start_end_range.py

[refactor] 9-9: Too few public methods (0/2)

(R0903)


[refactor] 6-6: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/models/mentee.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/mentee_program.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

🪛 Ruff (0.11.9)
backend/apps/mentorship/migrations/0001_initial.py

14-14: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


14-14: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


15-15: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


15-15: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


21-21: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


23-23: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


23-23: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


24-24: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


25-25: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


26-26: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


26-26: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


26-26: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


26-26: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


26-26: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


26-26: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


26-26: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


26-26: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


26-26: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


26-26: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


26-26: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


27-27: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


27-27: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


27-27: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


28-28: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


28-28: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


28-28: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


29-29: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


29-29: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


29-29: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


30-30: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


30-30: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


33-33: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


33-33: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


34-34: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


34-34: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


38-38: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


40-40: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


40-40: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


41-41: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


42-42: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


43-43: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


43-43: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


43-43: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


43-43: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


43-43: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


43-43: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


43-43: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


43-43: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


43-43: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


43-43: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


43-43: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


44-44: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


44-44: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


44-44: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


45-45: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


45-45: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


45-45: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


46-46: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


46-46: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


46-46: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


47-47: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


47-47: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


50-50: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


50-50: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


51-51: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


51-51: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


55-55: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


57-57: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


57-57: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


58-58: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


59-59: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


60-60: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


60-60: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


60-60: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


60-60: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


60-60: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


60-60: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


60-60: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


60-60: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


60-60: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


60-60: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


60-60: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


61-61: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


61-61: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


61-61: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


62-62: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


62-62: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


62-62: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


63-63: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


63-63: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


63-63: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


64-64: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


64-64: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


64-64: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


67-67: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


67-67: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


68-68: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


68-68: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


69-69: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


69-69: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


73-73: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


75-75: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


75-75: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


76-76: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


77-77: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


78-78: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


78-78: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


78-78: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


78-78: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


78-78: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


78-78: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


78-78: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


78-78: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


78-78: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


78-78: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


78-78: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


79-79: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


79-79: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


79-79: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


80-80: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


80-80: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


80-80: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


81-81: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


81-81: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


82-82: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


82-82: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


83-83: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


83-83: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


83-83: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


84-84: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


84-84: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


84-84: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


85-85: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


85-85: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


85-85: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


85-85: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


85-85: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


86-86: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


86-86: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


86-86: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


89-89: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


89-89: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


90-90: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


90-90: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


94-94: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


95-95: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


96-96: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


96-96: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


99-99: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


101-101: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


101-101: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


102-102: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


103-103: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


104-104: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


104-104: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


104-104: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


105-105: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


105-105: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


105-105: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


106-106: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


106-106: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


107-107: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


107-107: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


108-108: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


108-108: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


108-108: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


109-109: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


109-109: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


109-109: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


109-109: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


109-109: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


109-109: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


109-109: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


109-109: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


109-109: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


109-109: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


110-110: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


110-110: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


110-110: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


111-111: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


111-111: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


112-112: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


112-112: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


112-112: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


112-112: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


112-112: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


112-112: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


112-112: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


112-112: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


112-112: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


113-113: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


113-113: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


113-113: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


116-116: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


116-116: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


117-117: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


117-117: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


121-121: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


122-122: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


123-123: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


123-123: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


123-123: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


126-126: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


128-128: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


128-128: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


129-129: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


130-130: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


131-131: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


131-131: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


131-131: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


131-131: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


131-131: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


131-131: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


131-131: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


131-131: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


131-131: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


131-131: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


131-131: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


132-132: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


132-132: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


133-133: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


133-133: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


134-134: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


134-134: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


134-134: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


135-135: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


135-135: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


135-135: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


138-138: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


138-138: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


139-139: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


139-139: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


140-140: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


140-140: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


140-140: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


144-144: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


145-145: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


146-146: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


146-146: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


146-146: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


146-146: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


149-149: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


150-150: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


150-150: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


153-153: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


155-155: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


155-155: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


156-156: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


157-157: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


158-158: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


158-158: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


159-159: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


159-159: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


160-160: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


160-160: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


160-160: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


161-161: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


161-161: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


161-161: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


164-164: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


164-164: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


165-165: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


165-165: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


166-166: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


166-166: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)


166-166: Single quotes found but double quotes preferred

Replace single quotes with double quotes

(Q000)

🪛 GitHub Actions: Run CI/CD
backend/apps/mentorship/migrations/0001_initial.py

[error] 1-497: Ruff linting failed with 266 errors fixed automatically. Pre-commit hooks modified files to fix formatting and linting issues. Run 'pre-commit run --all-files' locally to reproduce.

🪛 Flake8 (7.2.0)
backend/apps/mentorship/models/__init__.py

[error] 1-1: '.mentee.Mentee' imported but unused

(F401)


[error] 2-2: '.mentee_module.MenteeModule' imported but unused

(F401)


[error] 3-3: '.mentee_program.MenteeProgram' imported but unused

(F401)


[error] 4-4: '.mentor.Mentor' imported but unused

(F401)


[error] 5-5: '.mentor_module.MentorModule' imported but unused

(F401)


[error] 6-6: '.module.Module' imported but unused

(F401)


[error] 7-7: '.program.Program' imported but unused

(F401)

backend/apps/mentorship/models/common/__init__.py

[error] 1-1: '.experience_level.ExperienceLevel' imported but unused

(F401)


[error] 2-2: '.matching_attributes.MatchingAttributes' imported but unused

(F401)


[error] 3-3: '.start_end_range.StartEndRange' imported but unused

(F401)

🔇 Additional comments (6)
backend/apps/mentorship/models/common/__init__.py (1)

1-3: LGTM! Package interface correctly implemented.

This is the standard Python pattern for package interfaces. The imports are re-exports that allow consumers to import directly from the common package namespace (e.g., from apps.mentorship.models.common import ExperienceLevel). The static analysis warnings about unused imports are false positives.

backend/apps/mentorship/models/__init__.py (1)

1-7: LGTM! Standard Django app model interface.

This follows the standard Django pattern of consolidating model imports in the app's models/__init__.py. This allows consumers to import models directly from the app (e.g., from apps.mentorship.models import Mentor, Mentee). The static analysis warnings about unused imports are false positives.

backend/apps/mentorship/models/mentee_program.py (1)

11-39: LGTM!

The model structure is well-designed with appropriate inheritance, foreign key relationships, and constraints. The unique_together constraint prevents duplicate enrollments, and the str method provides a clear representation.

backend/apps/mentorship/models/module.py (1)

64-71: To confirm which fields StartEndRange actually defines, let’s dump its class body. Please run:

#!/bin/bash
set -e

FILE="backend/apps/mentorship/models/common/start_end_range.py"

echo "=== Showing StartEndRange class definition ==="
# Print from class declaration through the next 200 lines
rg -n "class StartEndRange" -A 200 "$FILE"
backend/apps/mentorship/admin.py (1)

12-86: Well-structured admin configurations.

The admin classes are well-designed with appropriate configurations for list displays, search fields, and filters. The use of related field lookups (e.g., mentee__user__login, program__name) provides good user experience in the admin interface.

backend/apps/mentorship/migrations/0001_initial.py (1)

20-169: Well-designed mentorship schema with proper relationships.

The migration creates a comprehensive mentorship system with:

  • Proper one-to-one relationships with GitHub users
  • Many-to-many relationships with appropriate through tables
  • Good use of unique constraints and indexes
  • Appropriate field types and constraints

The schema supports complex mentorship scenarios with programs, modules, and enrollment tracking.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
backend/apps/mentorship/migrations/0001_initial.py (1)

203-208: Verbose name issue already identified.

The incorrect verbose_name for the mentor field has already been flagged in previous reviews.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c7b9a3 and 5ac60dd.

📒 Files selected for processing (1)
  • backend/apps/mentorship/migrations/0001_initial.py (1 hunks)
🧰 Additional context used
🪛 Pylint (3.3.7)
backend/apps/mentorship/migrations/0001_initial.py

[refactor] 9-9: Too few public methods (0/2)

(R0903)

🔇 Additional comments (5)
backend/apps/mentorship/migrations/0001_initial.py (5)

19-85: Well-structured Mentee model.

The model definition follows Django best practices with appropriate field types, relationships, and constraints. The use of JSONField for flexible domain and tag storage is a good design choice.


86-152: Consistent Mentor model structure.

The Mentor model appropriately mirrors the Mentee model structure, maintaining consistency in the domain model design.


304-391: Well-designed Program model.

The model effectively captures program requirements with appropriate use of ArrayField for multiple experience levels and proper constraints like unique name field.


402-451: Properly constrained intermediary model.

The MenteeProgram model correctly implements the many-to-many relationship with appropriate unique constraints to prevent duplicate enrollments.


467-502: Clean intermediary model design.

The MenteeModule model appropriately handles the mentee-module relationship with proper unique constraints.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
backend/apps/mentorship/migrations/0001_initial.py (1)

203-208: Fix incorrect verbose_name for mentor field.

The mentor field in the MentorModule model has verbose_name="Program" but should be verbose_name="Mentor" since it references a mentor, not a program.

                (
                    "mentor",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        to="mentorship.mentor",
-                        verbose_name="Program",
+                        verbose_name="Mentor",
                    ),
                ),
🧹 Nitpick comments (2)
backend/apps/mentorship/models/mentor.py (1)

33-40: Add defensive null check in str method.

While github_user is a required field, it could still be None during object creation or in edge cases, potentially causing an AttributeError.

    def __str__(self) -> str:
        """Return a human-readable representation of the mentor.

        Returns:
            str: The GitHub username of the mentor.

        """
-        return self.github_user.login
+        return self.github_user.login if self.github_user else "Unlinked Mentor"
backend/apps/mentorship/models/mentee.py (1)

42-49: Add defensive null check in str method.

Similar to the Mentor model, while github_user is required, it could still be None during object creation or edge cases, potentially causing an AttributeError.

    def __str__(self) -> str:
        """Return a human-readable representation of the mentee.

        Returns:
            str: The GitHub username of the mentee.

        """
-        return self.github_user.login
+        return self.github_user.login if self.github_user else "Unlinked Mentee"
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ac60dd and 7f79adb.

📒 Files selected for processing (5)
  • backend/apps/mentorship/admin.py (1 hunks)
  • backend/apps/mentorship/migrations/0001_initial.py (1 hunks)
  • backend/apps/mentorship/models/mentee.py (1 hunks)
  • backend/apps/mentorship/models/mentor.py (1 hunks)
  • backend/apps/mentorship/models/module.py (1 hunks)
🧰 Additional context used
🪛 Pylint (3.3.7)
backend/apps/mentorship/admin.py

[refactor] 12-12: Too few public methods (0/2)

(R0903)


[refactor] 23-23: Too few public methods (0/2)

(R0903)


[refactor] 42-42: Too few public methods (0/2)

(R0903)


[refactor] 54-54: Too few public methods (0/2)

(R0903)


[refactor] 69-69: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/migrations/0001_initial.py

[refactor] 9-9: Too few public methods (0/2)

(R0903)

backend/apps/mentorship/models/mentee.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/mentor.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)


[refactor] 11-11: Too few public methods (1/2)

(R0903)

backend/apps/mentorship/models/module.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests
🔇 Additional comments (1)
backend/apps/mentorship/admin.py (1)

1-94: LGTM - Well-structured admin configurations.

The admin configurations provide comprehensive management interfaces for all mentorship models with appropriate search fields, list displays, and filters. All admin classes are properly registered.

Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
25.0% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
backend/apps/mentorship/models/module.py (1)

63-70: Previous field name issue has been resolved.

The save method now correctly uses started_at and ended_at field names, addressing the previous review comment about incorrect field references. The logic properly inherits dates from the associated program when not already set.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f79adb and 0ea7eaf.

📒 Files selected for processing (1)
  • backend/apps/mentorship/models/module.py (1 hunks)
🧰 Additional context used
🪛 Pylint (3.3.7)
backend/apps/mentorship/models/module.py

[refactor] 14-14: Too few public methods (0/2)

(R0903)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests

@arkid15r arkid15r requested a review from kasya June 25, 2025 00:23
Copy link
Collaborator

@kasya kasya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM again!
Left one question ⬇️

@arkid15r arkid15r enabled auto-merge June 25, 2025 02:06
@arkid15r arkid15r added this pull request to the merge queue Jun 25, 2025
Merged via the queue into OWASP:main with commit 06cfb27 Jun 25, 2025
22 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement Mentorship App with Program and Module Structure
6 participants