When fields need to be filled programmatically in Django Rest Framework, the pre_save method may be overridden in the APIView, and the needed fields can be populated there, like:
def pre_save(self, obj):
obj.owner = self.request.user
This works great for flat objects, but in case of nested situations, the nested object cannot be accessed in the pre_save method. The only solution I found so far is to override the save_object method, and check if the object is an instance of the nested class, and if so, populate that field there. Although this works, I don't like the solution, and would like to know if anyone found a better way?
Demonstrating the situation:
class Notebook(models.Model):
owner = models.ForeignKey(User)
class Note(models.Model):
owner = models.ForeignKey(User)
notebook = models.ForeignKey(Notebook)
note = models.TextField()
class NoteSerializer(serializers.ModelSerializer):
owner = serializers.Field(source='owner.username')
class Meta:
model = Note
fields = ('note', 'owner')
class NotebookSerializer(serializers.ModelSerializer):
notes = NoteSerializer(many=True)
owner = serializers.Field(source='owner.username')
class Meta:
model = Notebook
fields = ('notes', 'owner')
def save_object(self, obj, **kwargs):
if isinstance(obj, Note):
obj.owner = obj.notebook.owner
return super(NotebookSerializer, self).save_object(obj, **kwargs)
class NotebookCreateAPIView(CreateAPIView):
model = Notebook
permission_classes = (IsAuthenticated,)
serializer_class = NotebookSerializer
def pre_save(self, obj):
obj.owner = self.request.user
Before asking why don't I use different endpoints for creating notebooks and notes separately, let me say that I do that, but I also need a functionality to provide initial notes on creation of the notebook, so that's why I need this kind of endpoint as well.
Also, before I figured out this hackish solution, I actually expected that I will have to override the save_object method of the NoteSerializer class itself, but it turned out in case of nested objects, it won't even be called, only the root object's save_objects method, for all the nested objects, but I guess it was a design decision.
So once again, is this solvable in a more idiomatic way?