Spaces:
Sleeping
Sleeping
| 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]}' | |