Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run Serializer's validation only when creating a new post

Tags:

I have 2 views - one of them uses create and another one uses RetrieveUpdateDestroyAPIView. Both use same Serializer class. I need title validation only when creating a new post, not when updating a post.
I have title validation error when I'm updating some post with "PUT" request.
How can I fix this?

class StoreApiView(mixins.CreateModelMixin, generics.ListAPIView):
    lookup_field = 'pk'
    serializer_class = ProductSerializer

    def get_queryset(self):
        qs = Product.objects.all()
        query = self.request.GET.get('q')
        if query is not None:
            qs = qs.filter(
                Q(title__icontains=query) |
                Q(description__icontains=query)
            ).distinct()
        return qs

    def perform_create(self, serializer):
        serializer.save(author=self.request.user)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class StoreRucView(generics.RetrieveUpdateDestroyAPIView):
    lookup_field = 'pk'
    serializer_class = ProductSerializer
    permission_classes = [IsOwnerOrReadOnly]


    def get_queryset(self):
        return Product.objects.all()

This is the serializer class full code:

class ProductSerializer(ModelSerializer):
    product_ratings = ProductRatingSerializer(many=True,read_only=True)
    product_badges_set = ProductBadgesSerializer(many=True,read_only=True)

    author = serializers.SerializerMethodField()
    category = serializers.SerializerMethodField()

    def get_author(self, obj):
        return obj.author.first_name+' '+obj.author.last_name

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

    class Meta:
        model = Product
        fields = [
            'product_id',
            'author',
            'category',
            'title',
            'description',
            'price',
            'level',
            'video_length',
            'created_date',
            'updated_date',
            'product_ratings',
            'product_badges_set',
        ]
        read_only_fields = ['product_id', 'created_date', 'updated_date', 'author']

    def validate_title(self, value):

        qs = Product.objects.filter(title__iexact=value)
        if self.instance:
            qs.exclude(pk=self.instance.pk)
        if qs.exists():
            raise serializers.ValidationError("this title is already used")
        return value
like image 477
devmrh Avatar asked Feb 12 '18 09:02

devmrh


1 Answers

You can pass additional context in serializer. And check this context's value in validate_title. In view:

def get_serializer_context(self):
    context = super().get_serializer_context()
    context['is_create'] = True 
    return context 

def perform_create(self, serializer):
    serializer.save(author=self.request.user)

In serializer:

def validate_title(self, value):
  if self.context.get('is_create'):   
    qs = Product.objects.filter(title__iexact=value)
    if self.instance:
        qs.exclude(pk=self.instance.pk)
    if qs.exists():
        raise serializers.ValidationError("this title is already used")
    return value
like image 150
neverwalkaloner Avatar answered Oct 11 '22 17:10

neverwalkaloner