DRF serializer validation - discard failed items, keep successful ones?
I have an endpoint (POST, APIView) which expects larger chunks of data that needs to be validated using serializers. However, for many reasons there are times where I'd like to discard a few of them that fail validation. The rest, I still want to add.
E.g I'd like to run :
serializer = ListingSerializer(data=request.data, many=True)
if serializer.is_valid():
serializer.save()
Lets say we have a table of listings which has a foreign key to a company table. Therefore I have a nested company serializer as a field. A company only has a name. In order to save some performance I fetch all companies in the init method so is_valid() only makes one query (similar to a select_related).
The problem here is that if a single company did not exist, the entire is_valid() will fail and thus I cant run serializer.save(). Is there any elegant way to solve this by discarding the individual items that fail is_valid() so that I can run serializer.save()?
class CompanyStringSerializer(serializers.ModelSerializer):
class Meta:
model = Company
fields = ("name",)
class ListingSerializer():
company = CompanyStringSerializer()
def __init__(self, *args, **kwargs):
"""
This is executed when the serializer initializes (meaning the query will only run once)
"""
self.companies = Company.objects.filter(enabled=True)
super().__init__(*args, **kwargs)
def validate_company(self, value):
"""
This will run on each item & check if the items company name exists in the list of companies
"""
try:
company = next(
item for item in self.companies if item.name == value["name"]
)
except StopIteration:
print(f"company did not exist: {value['name']}")
raise ValidationError("No such company exists")
return company
class Meta:
model = Listing
list_serializer_class = ListingListSerializer
fields = "__all__"