gapguide-api / apps /resources /models.py
arifRB's picture
Deploy GapGuide backend (Docker)
ffd36e0 verified
Raw
History Blame Contribute Delete
3.17 kB
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
class Resource(models.Model):
DIFFICULTY_CHOICES = [
('BEGINNER', 'Beginner'),
('INTERMEDIATE', 'Intermediate'),
('ADVANCED', 'Advanced'),
]
TYPE_CHOICES = [
('VIDEO', 'Video'),
('COURSE', 'Course'),
('ARTICLE', 'Article'),
('DOCS', 'Docs'),
]
title = models.CharField(max_length=300)
provider = models.CharField(max_length=100)
url = models.URLField(max_length=500, unique=True)
difficulty_level = models.CharField(max_length=20, choices=DIFFICULTY_CHOICES)
duration = models.IntegerField(
help_text='Total duration in minutes.',
validators=[MinValueValidator(0)],
)
type = models.CharField(max_length=20, choices=TYPE_CHOICES)
rating = models.FloatField(
default=3.5,
validators=[MinValueValidator(0.0), MaxValueValidator(5.0)],
help_text='Curator-assigned 0.0-5.0 rating used by recommendation ranking.',
)
skills = models.ManyToManyField(
'skills.Skill',
through='SkillResource',
related_name='resources',
)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['title']
def __str__(self):
return f'{self.title} ({self.provider})'
class SkillResource(models.Model):
skill = models.ForeignKey('skills.Skill', on_delete=models.CASCADE)
resource = models.ForeignKey(Resource, on_delete=models.CASCADE)
relevance_score = models.FloatField(
default=1.0,
validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
help_text='0.0-1.0 how relevant this resource is to the skill.',
)
class Meta:
unique_together = [['skill', 'resource']]
def __str__(self):
return f'{self.skill.skill_name} - {self.resource.title} ({self.relevance_score:.2f})'
class ResourceCheckpoint(models.Model):
SOURCE_CHOICES = [
('manual', 'Manual'),
('jsonld', 'schema.org JSON-LD'),
('html', 'HTML parse'),
('youtube_api', 'YouTube API'),
('playwright', 'Playwright'),
('fcc_github', 'freeCodeCamp GitHub'),
]
resource = models.ForeignKey(
Resource,
on_delete=models.CASCADE,
related_name='checkpoints',
)
order_index = models.IntegerField(
validators=[MinValueValidator(1)],
help_text='1-based position within the resource.',
)
title = models.CharField(max_length=500)
url_fragment = models.CharField(
max_length=500, blank=True, default='',
help_text='Optional anchor/path suffix linking to this module.',
)
estimated_minutes = models.IntegerField(null=True, blank=True)
source = models.CharField(max_length=20, choices=SOURCE_CHOICES, default='manual')
extracted_at = models.DateTimeField(null=True, blank=True)
class Meta:
unique_together = [['resource', 'order_index']]
ordering = ['resource', 'order_index']
def __str__(self):
return f'{self.resource.title} #{self.order_index}: {self.title[:60]}'