Search code examples
djangovalidationmany-to-manydjango-rest-frameworkunique

Unique validation error in many to many relations


I have a serializer with an unique name field :

class ProductTypeSerializer(serializers.ModelSerializer):
    url = serializers.URLField(source='get_absolute_url', read_only=True)
    id = serializers.IntegerField(required=False)
    name = serializers.CharField(validators=[
        UniqueValidator(queryset=ProductType.objects.all())
    ])
    user =  UserSerializer(required=False)
    publish = serializers.BooleanField(required=False)

    class Meta:
        model = ProductType
        fields = ('url',
                  'id',
                  'name',
                  'publish',
                  'user',
                  'register_date')

On the other hand, there is another serializer with a many-to-many relation to the serializer with unique name field :

class BrandSerializer(serializers.ModelSerializer):
    url = serializers.URLField(source='get_absolute_url', read_only=True)
    id = serializers.IntegerField(required=False)
    name = serializers.CharField()
    product_types = ProductTypeSerializer(many=True, required=False)
    user = UserSerializer(required=False)

    class Meta:
        model = Brand
        fields = ('url',
                  'id',
                  'name',
                  'product_types',
                  'publish',
                  'user',
                  'register_date')

    def create(self, validated_data):
        print  'validated_data:', validated_data
        request = self.context['request']
        name = validated_data.get('name', None)
        publish = validated_data.get('publish', False)
        product_types_data = validated_data.pop('product_types', None)
        product_types = []
        for pt in product_types_data:
            product_type = ProductType.objects.get(pk=pt['id'])
            product_types.append(product_type)
        obj = Brand.objects.create(
            name=name,
            publish=publish,
            user=request.user
           )
        obj.product_types.add(*product_types)
    return obj

I get an unique validation error when I post brand data with the BrandSerializer:

{"product_types":[{"name":["This field must be unique."]}]}

How to suppress the validation of ProductTypeSerializer when we create a brand with BrandSerializer?


Solution

  • Set your product_type field as read_only field and to create it, get data from request.data not validated data

    class BrandSerializer(serializers.ModelSerializer):
        url = serializers.URLField(source='get_absolute_url', read_only=True)
        id = serializers.IntegerField(required=False)
        name = serializers.CharField()
        product_types = ProductTypeSerializer(many=True, read_only=True)
        user = UserSerializer(required=False)
    
        class Meta:
            model = Brand
            fields = ('url',
                      'id',
                      'name',
                      'product_types',
                      'publish',
                      'user',
                      'register_date')
    
        def create(self, validated_data):
            print  'validated_data:', validated_data
            request = self.context['request']
            name = validated_data.get('name', None)
            publish = validated_data.get('publish', False)
            product_types_data = request.data.get('product_types', None)
            product_types = []
            for pt in product_types_data:
                product_type = ProductType.objects.get(pk=pt['id'])
                product_types.append(product_type)
            obj = Brand.objects.create(
                name=name,
                publish=publish,
                user=request.user
               )
            obj.product_types.add(*product_types)
        return obj
    

    And if you want to validate if product_type was passed as parameter in the request, you can do it on the clean method