coredumped0x
coredumped0x

Reputation: 848

DRF: based on the validation of field x, stop the validation of field y and delete from data

I have a form where the user can post a deal, and for that they can choose to either upload an image (x), or provide a link to an already uploaded one on the internet (y). So when either of the fields exists and is valid, I would like to dismiss the other field from validation. Here is a simplified Model:

class Deal(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='deals',
                            on_delete=models.CASCADE)
    title = models.CharField(max_length=1024, blank=False, null=False)
    slug = models.SlugField(max_length=1024, unique=True, blank=True)
    poster = models.ImageField()
    poster_url = models.CharField(max_length=1024, blank=True, null=True)
    created = models.DateField(auto_now_add=True)
    updated = models.DateField(auto_now=True)

And here's my serializer:

class DealSerializer(serializers.ModelSerializer):

    user = UserSerializer(many=False, read_only=True)

    class Meta:
        model = Deal
        fields = '__all__'

    def validate_poster_url(self, value):
        poster = self.initial_data.get("poster")
        if value == "" and poster == "":
            # set to mutable
            self.initial_data._mutable = True
            self.initial_data.delete("poster")
            raise serializers.ValidationError(
                "Deal must either have a Poster or a Poster URL")
        return value

    def validate_poster(self, value):
        poster_url = self.initial_data.get("poster_url")
        if value != "":
            if poster_url == "":
                # set to mutable
                self.initial_data._mutable = True
                self.initial_data.delete("poster_url")
                raise serializers.ValidationError(
                    "Deal must either have a Poster or a Poster URL")
        return value

    def create(self, validated_data):
        deal, _ = Deal.objects.update_or_create(**validated_data)
        return deal

When I submit for example a poster_url, the poster field still gets validated and I get a validation error:

poster: ["The submitted data was not a file. Check the encoding type on the form."]

I have tried to "delete" the required field from the initial_data as an attempt, but that wouldn't work, and I also tried to use the global validate(), but it was never called. I would really appreciate any help. Thank you.

Upvotes: 1

Views: 183

Answers (1)

Dušan Maďar
Dušan Maďar

Reputation: 9909

Well, Deal.poster is not optional, so that's why Django complains. I don't think you can handle this on the serializer level. Take a look at Django - how to make ImageField/FileField optional?.

Upvotes: 1

Related Questions