Skip to content

Commit

Permalink
Modify Skill app: changes on skill_type model (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
albertoleoncio authored Mar 6, 2025
1 parent d719a53 commit 7d53df2
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 10 deletions.
40 changes: 40 additions & 0 deletions skills/migrations/0005_remove_skill_skill_type_skill_skill_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 4.2.11 on 2025-02-27 21:51

from django.db import migrations, models
import django.db.models.deletion
from skills.models import Skill

def move_skill_type_fk(apps, schema_editor): # pragma: no cover
for skill in apps.get_model('skills', 'Skill').objects.all():
skill.skill_class = skill.skill_type.all().first()
skill.save()

def move_skill_type_m2m(apps, schema_editor): # pragma: no cover
for skill in apps.get_model('skills', 'Skill').objects.all():
skill.skill_type.add(skill.skill_class)
skill.save()


class Migration(migrations.Migration):

dependencies = [
('skills', '0004_alter_skill_skill_type_and_more'),
]

operations = [
migrations.AddField(
model_name='skill',
name='skill_class',
field=models.ForeignKey(blank=True, help_text='ID of the another skill that this skill is a subtype of.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='skills.skill', verbose_name='Skill type'),
),
migrations.RunPython(move_skill_type_fk, move_skill_type_m2m),
migrations.RemoveField(
model_name='skill',
name='skill_type',
),
migrations.RenameField(
model_name='skill',
old_name='skill_class',
new_name='skill_type',
),
]
18 changes: 15 additions & 3 deletions skills/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.db import models
from django.core.validators import RegexValidator
from django.utils import timezone
from django.core.exceptions import ValidationError


qid_form_validator = RegexValidator(regex=r"^Q\d+$", message="Field must be in the format \"Q123456789\"")
Expand All @@ -13,12 +14,23 @@ class Skill(models.Model):
help_text="Wikidata item ID of the skill.",
validators=[qid_form_validator]
)
skill_type = models.ManyToManyField(
skill_type = models.ForeignKey(
"self",
verbose_name="Skill type", symmetrical=False, blank=True,
verbose_name="Skill type", blank=True, on_delete=models.SET_NULL, null=True,
help_text="ID of the another skill that this skill is a subtype of."
)
skill_date_of_creation = models.DateTimeField(default=timezone.now)

def __str__(self):
return self.skill_wikidata_item
return self.skill_wikidata_item

def save(self, *args, **kwargs):
if self.skill_type:
parent_skill = self.skill_type
level = 1
while parent_skill.skill_type:
parent_skill = parent_skill.skill_type
level += 1
if level >= 3:
raise ValidationError("Skills cannot be nested more than 3 levels deep.")
super().save(*args, **kwargs)
19 changes: 19 additions & 0 deletions skills/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.test import TestCase
from django.utils import timezone
from skills.models import Skill
from django.core.exceptions import ValidationError

class SkillModelTest(TestCase):
def test_skill_creation(self):
Expand All @@ -15,3 +16,21 @@ def test_skill_str(self):
skill_wikidata_item="Q123456789"
)
self.assertEqual(str(skill), "Q123456789")

def test_skill_four_levels_deep(self):
skill1 = Skill.objects.create(
skill_wikidata_item="Q123456789"
)
skill2 = Skill.objects.create(
skill_wikidata_item="Q123456780",
skill_type=skill1
)
skill3 = Skill.objects.create(
skill_wikidata_item="Q123456781",
skill_type=skill2
)
with self.assertRaises(ValidationError):
Skill.objects.create(
skill_wikidata_item="Q123456782",
skill_type=skill3
)
8 changes: 1 addition & 7 deletions skills/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ def test_create_skill(self):
serializer = SkillSerializer(skill)
self.assertEqual(response.data, serializer.data)

options_response = self.client.options('/skill/1/')
expected_choices = [{'value': 1, 'display_name': 'Q123456789'}, {'value': 2, 'display_name': 'Q987654321'}]
self.assertEqual(options_response.status_code, status.HTTP_200_OK)
self.assertEqual(options_response.data['actions']['PUT']['skill_type']['choices'], expected_choices)

def test_create_skill_nostaff(self):
self.user.is_staff = False
self.user.save()
Expand Down Expand Up @@ -112,8 +107,7 @@ def setUp(self):
self.client = APIClient()
self.client.force_authenticate(self.user)
first = Skill.objects.create(skill_wikidata_item='Q123456789')
second = Skill.objects.create(skill_wikidata_item='Q987654321')
second.skill_type.add(first)
Skill.objects.create(skill_wikidata_item='Q987654321', skill_type=first)

def test_get_skills_by_type(self):
response = self.client.get('/skills_by_type/1/')
Expand Down

0 comments on commit 7d53df2

Please sign in to comment.