Alan
Alan

Reputation: 313

Django Restful API Design Validation Logic

Here I have an endpoint to create media content for users. The endpoint works, but I have a feeling my design implementation is incorrect.

Should validation logic be contained in serializers create? Is this bad practice? I attempted to move validation logic to models.py, but ran into issues with accessing the model, specifically this line - self.model(user=user, category=category).

view.py

from rest_framework import status
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from .models import UserMedia
from .renderers import UserMediaSerializerJSONRenderer
from .serializers import UserMediaSerializer


class UserMediaCreateAPIView(APIView):
    permission_classes = (IsAuthenticated,)
    renderer_classes = (UserMediaSerializerJSONRenderer,)
    serializer_class = UserMediaSerializer

    def post(self, request):
        userMedia = request.data.get('userMedia', {})
        serializer = self.serializer_class(data=userMedia)
        serializer.is_valid(raise_exception=True)
        serializer.save(user=request.user, category=userMedia['category'])

        return Response(serializer.data, status=status.HTTP_201_CREATED)

serializers.py

from rest_framework import serializers

from .models import UserMedia


class UserMediaSerializer(serializers.ModelSerializer):
    category = serializers.CharField(allow_blank=False, required=True)

    class Meta:
        model = UserMedia
        fields = ('category',)
        read_only_fields = ('category',)

    def get_category(self, obj):
        if obj.category:
            return obj.category

        return 'N/A'

    def create(self, validated_data):
        if validated_data['user'] is None:
            raise TypeError('User media must have a user')

        if validated_data['category'] is None:
            raise TypeError('User media must have a category.')

        if validated_data['category'] not in dict(UserMedia.CATEGORY_CHOICES):
            raise TypeError('User media category is not available.')

        userMedia = UserMedia(**validated_data)
        userMedia.save()
        return userMedia

models.py

from django.db import models

class UserMedia(models.Model):
    user = models.ForeignKey('authentication.User', on_delete=models.CASCADE, related_name='media')

    MUSIC = 'M'
    VIDEO = 'V'
    CATEGORY_CHOICES = (
        (MUSIC, 'Music'),
        (VIDEO, 'Video'),
    )
    category = models.CharField(max_length=1, choices=CATEGORY_CHOICES, blank=False)

Upvotes: 0

Views: 54

Answers (1)

Taylor
Taylor

Reputation: 1253

The validation should be done in your view. The serializers should just be for serializing data. The validation should be done in your view then the serializer is called from your view. As far as this line self.model(user=user, category=category) is concerned it does not appear that you ever import user any where.

Upvotes: 1

Related Questions