Implementación de Endpoints para la Gestión de Cursos en Django REST Framework

Configuración de Rutas

Para exponer los recursos de nuestra API, utilizamos el sistema de enrutamiento de Django REST Framework para registrar los ViewSets de categorías y cursos.

from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter()
router.register('categorias', views.CategoryViewSet, basename='course-categories')
router.register('catalogo', views.AcademyCourseViewSet, basename='course-list')

Definición de Vistas y Lógica de Filtrado

El siguiente ViewSet gestiona la recuperación de cursos, integrando capacidades de búsqueda, ordenación y filtrado avanzado mediante el uso de django-filter.

from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
from . import models, serializers, pagination, filters

class CategoryViewSet(GenericViewSet, ListModelMixin):
    """
    Vista para listar las categorías de cursos activas.
    """
    queryset = models.CourseCategory.objects.filter(is_delete=False, is_show=True)
    serializer_class = serializers.CategorySerializer

class AcademyCourseViewSet(GenericViewSet, ListModelMixin):
    """
    Vista principal para el catálogo de cursos con soporte para paginación y filtros.
    """
    queryset = models.AcademyCourse.objects.filter(is_delete=False, is_show=True)
    serializer_class = serializers.AcademyCourseSerializer
    pagination_class = pagination.StandardPagination
    
    # Configuración de motores de filtrado
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    
    # Campos habilitados para búsqueda y ordenación
    search_fields = ['title', 'description']
    ordering_fields = ['id', 'price', 'enrolled_students']
    
    # Clase personalizada para filtros de rango
    filterset_class = filters.CourseRangeFilter

Filtros Personalizados de Rango

Implementamos una clase de filtrado para permitir a los usuarios buscar cursos dentro de un rango de precios específico.

from django_filters import rest_framework as filters
from .models import AcademyCourse

class CourseRangeFilter(filters.FilterSet):
    coste_min = filters.NumberFilter(field_name='price', lookup_expr='gte')
    coste_max = filters.NumberFilter(field_name='price', lookup_expr='lte')

    class Meta:
        model = AcademyCourse
        fields = ['category', 'coste_min', 'coste_max']

Esquema de Paginación

Definimos una estructura de pgainación personalizada para controlar el volumen de datos enviados al cliente por cada solicitud.

from rest_framework.pagination import PageNumberPagination

class StandardPagination(PageNumberPagination):
    page_size = 5  # Cantidad por defecto
    page_query_param = 'p'
    page_size_query_param = 'limit'
    max_page_size = 20

Lógica en el Modelo y Propiedades Dinámicas

En el modelo de datos, utilizamos el decorador @property para generar campos calculados que facilitan la serialización de datos complejos, como la vista previa de las lecciones.

from django.db import models

class AcademyCourse(BaseModel):
    # ... campos del modelo ...

    @property
    def label_type(self):
        return self.get_course_type_display()

    @property
    def preview_lessons(self):
        """
        Retorna una lista con las primeras 4 lecciones de todos los capítulos.
        """
        items = []
        for chapter in self.chapters.all():
            for lesson in chapter.lessons.all():
                items.append({
                    'title': lesson.name,
                    'url': lesson.video_url,
                    'duration': lesson.length,
                    'is_free': lesson.is_preview,
                })
                if len(items) >= 4:
                    return items
        return items

class Instructor(BaseModel):
    # ... campos del modelo ...
    @property
    def profession(self):
        return self.get_role_display()

Serialización de Datos

Finalmente, configuramos los serializadores para transformar los modelos en formato JSON, encluyendo la anidación del instructor dentro de cada curso.

from rest_framework import serializers
from . import models

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = models.CourseCategory
        fields = ('id', 'name')

class InstructorSerializer(serializers.ModelSerializer):
    role = serializers.ReadOnlyField(source='profession')

    class Meta:
        model = models.Instructor
        fields = ('name', 'role', 'biography', 'avatar')

class AcademyCourseSerializer(serializers.ModelSerializer):
    teacher_info = InstructorSerializer(source='instructor', read_only=True)
    type_display = serializers.ReadOnlyField(source='label_type')
    lessons_list = serializers.ReadOnlyField(source='preview_lessons')

    class Meta:
        model = models.AcademyCourse
        fields = (
            'id', 'title', 'cover_image', 'price', 
            'enrolled_students', 'type_display', 
            'teacher_info', 'lessons_list'
        )

Etiquetas: django-rest-framework Python web-api backend

Publicado el 7-16 09:48