user1125177
user1125177

Reputation: 345

Validation is never fired

I have two models:

class Manufacturer(models.Model):
  name = models.CharField(max_length = 100)

class Car(models.Model):
  manufacturer = models.ForeignKey(Manufacturer, blank = True, null = True)

My serialisers:

class ManufacturerSerializer(serializers.ModelSerializer):
  class Meta:
    model = Manufacturer
    fields = ('id', 'name')

class CarSerializer(serializers.ModelSerializer):
  manufacturer = Manufact  

  class Meta:
    model = Car
    fields = ('id', 'name', 'manufacturer')

  def validate(self, attrs):
    try:
      attrs['manufacturer'] = Manufacturer.objects.get(pk = attrs['manufacturer'])
    except Manufacturer.DoesNotExist:
      raise ValidationError(_('Not found'))

    return attrs

My views:

class CarList(generics.ListCreateAPIView):
  queryset = Car.objects.all()
  serializer_class = CarSerializer

When I try to add a new Car calling POST /cars/ I get a validation error manufacturer is a required field. Car model expects manufacturer field to be Manufacturer object but to make messages small I pass it the manufacturer_id instead.

I know that should raise a ValidationError so to fix this I added a validate(..) to my CarSerializer so during validation I check if Manufacturer by this ID exists and I assign it to attrs.

Problem is this validate(..) is never called I even tried adding a post() method to CarList view and manually calling is_valid() to no success.

But I still get validation errors which I assume are coming from the Model.

Upvotes: 1

Views: 40

Answers (1)

Tomas Walch
Tomas Walch

Reputation: 2305

It doesn't work because you are complicating things. The ManufacturerSerializer is not necessary (for this view anyway). By default the 'manufacturer' field will be represented as a PrimaryKeyRelatedField which will resolve your manufacturer_id to a Manufacturer object automatically, so you don't need your validate method either.

Updated serializers:

class CarPostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Car
        fields = ('id', 'name', 'manufacturer')

class CarGetSerializer(CarPostSerializer):
    manufacturer = ManufacturerSerializer()

Updated view:

class CarList(generics.ListCreateAPIView):
    queryset = Car.objects.all()

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return CarPostSerializer
        else:
            return CarGetSerializer

Upvotes: 1

Related Questions