Plantilla Acceso Libre 20 Feb, 2026

Template: API REST completa con Django REST Framework

API REST production-ready con DRF. Incluye serializers, viewsets, paginación, filtros, throttling, documentación con drf-spectacular y tests.

#django #drf #api #rest #backend

Contenido

API REST Completa con Django REST Framework

Estructura profesional de API REST con DRF: serializers, viewsets, permisos, paginación y filtros. Todo listo para producción.

Instalación

pip install djangorestframework drf-spectacular django-filter

Settings

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
    'PAGE_SIZE': 20,
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',
        'rest_framework.filters.OrderingFilter',
    ],
    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle',
    ],
    'DEFAULT_THROTTLE_RATES': {
        'anon': '100/hour',
        'user': '1000/hour',
    },
}

Serializers con validación

from rest_framework import serializers

class PostSerializer(serializers.ModelSerializer):
    author_name = serializers.CharField(source='author.get_full_name', read_only=True)
    reaction_count = serializers.IntegerField(read_only=True)

    class Meta:
        model = Post
        fields = ['id', 'title', 'content', 'category', 'author', 'author_name',
                  'reaction_count', 'created_at', 'updated_at']
        read_only_fields = ['author', 'created_at', 'updated_at']

    def validate_title(self, value):
        if len(value) < 10:
            raise serializers.ValidationError("Mínimo 10 caracteres")
        return value

    def create(self, validated_data):
        validated_data['author'] = self.context['request'].user
        return super().create(validated_data)


class PostDetailSerializer(PostSerializer):
    comments = serializers.SerializerMethodField()

    class Meta(PostSerializer.Meta):
        fields = PostSerializer.Meta.fields + ['comments']

    def get_comments(self, obj):
        return CommentSerializer(obj.comment_set.all()[:20], many=True).data

ViewSet con filtros

from rest_framework import viewsets, permissions, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django_filters import rest_framework as filters

class PostFilter(filters.FilterSet):
    created_after = filters.DateTimeFilter(field_name='created_at', lookup_expr='gte')
    category = filters.ChoiceFilter(choices=Post.CATEGORY_CHOICES)

    class Meta:
        model = Post
        fields = ['category', 'author']

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.select_related('author').annotate(
        reaction_count=Count('reaction')
    ).order_by('-created_at')
    filterset_class = PostFilter
    search_fields = ['title', 'content']
    ordering_fields = ['created_at', 'reaction_count']

    def get_serializer_class(self):
        if self.action == 'retrieve':
            return PostDetailSerializer
        return PostSerializer

    def get_permissions(self):
        if self.action in ['update', 'partial_update', 'destroy']:
            return [permissions.IsAuthenticated(), IsAuthorOrReadOnly()]
        return [permissions.IsAuthenticatedOrReadOnly()]

    @action(detail=True, methods=['post'])
    def react(self, request, pk=None):
        post = self.get_object()
        _, created = Reaction.objects.get_or_create(user=request.user, post=post)
        if not created:
            Reaction.objects.filter(user=request.user, post=post).delete()
            return Response({"status": "removed"})
        return Response({"status": "added"}, status=status.HTTP_201_CREATED)

URLs

from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('posts', PostViewSet)
router.register('comments', CommentViewSet)

urlpatterns = [
    path('api/v1/', include(router.urls)),
    path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
    path('api/docs/', SpectacularSwaggerView.as_view(), name='docs'),
]

Recurso Externo

Este recurso incluye un enlace externo. Regístrate para acceder.

Inicia Sesión para Acceder

Únete a la Comunidad

Regístrate gratis para descargar archivos, guardar recursos en favoritos, ganar XP y acceder a cursos y el foro de la comunidad.

¿Ya tienes cuenta? Inicia sesión

Erik Taveras

Autor

Erik Taveras

Recursos Relacionados