I'm trying to override my serializer's save()
method (as per the docs) to support bulk instance creation. At the moment, I have something that looks like this (skip the code if you like, it's just for context. The real issue is I can't make any of my own serializer methods).
serializers.py
class BulkWidgetSerializer(serializers.ModelSerializer):
""" Serialize the Widget data """
#http://stackoverflow.com/questions/28200485/
some_foreign_key = serializers.CharField(source='fk_fizzbuzz.name', read_only=False)
class Meta:
model = Widget
fields = (
'some_foreign_key',
'uuid',
'foobar',
)
# Normally we would set uuid to read_only, but then it won't be available in the self.validate()
# method. We also need to take the validator off this field to remove the UNIQUE constraint, and
# perform the validation ourselves.
# See https://github.com/encode/django-rest-framework/issues/2996 and
# https://stackoverflow.com/a/36334825/3790954
extra_kwargs = {
'uuid': {'read_only': False, 'validators': []},
}
def validate(self, data):
return super(WidgetSerializer, self).validate(self.business_logic(data))
def save(self):
print("---------Calling save-----------")
more_business_logic()
instances = []
for widget in self.validated_data:
instances.append(Widget(**self.validated_data))
Widget.objects.bulk_create(instances)
return instances
viewset.py
class WidgetViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = BulkWidgetSerializer
pagination_class = WidgetViewSetPagination
lookup_field = 'uuid'
def partial_update(self, request):
serializer = self.get_serializer(data=request.data,
many=isinstance(request.data, list),
partial=True)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
pdb.set_trace()
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
Then I get new Wiget instances in the database, but their properties indicate that the more_business_logic()
call in save()
didn't occur. However, I do get feedback indicating that business_logic
in validate()
call occurred.
I presume from this that I'm somehow still stuck with the super
class's save()
? How can I override this method?
Edit:
When I rename save()
to newsave()
in both files, and try to call it in the ViewSet, I get:
AttributeError: 'ListSerializer' object has no attribute 'newsave'
What's going on? Inspecting with pdb
at the breakpoint shows that it is indeed a BulkWidgetSerializer
. Inspecting in the shell shows newsave
is definitely a method of that class:
>>>'newsave' in [func for func in dir(BulkWidgetSerializer) if callable(getattr(BulkWidgetSerializer, func))]
True
Moreover, if I create my own test method in the serializer class:
def test_method(self):
print("Successful test method")
I can't call that either!
>>> serializer.test_method()
AttributeError: 'ListSerializer' object has no attribute 'test_method'