I have the following structure of Parent and Child models, where the child references the parent.
class ParentModel(models.Model):
name = models.CharField(max_length=255)
class ChildModel(models.Model):
name = models.CharField(max_length=255)
parent = models.ForeignKey(
ParentModel, related_name='children', on_delete=models.CASCADE
)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
class ParentSerializer(serializers.ModelSerializer):
class Meta:
model = ParentModel
fields = (
'name',
'children',
)
class ChildSerializer(serializers.ModelSerializer):
class Meta:
models = ChildModel
fields = (
'name'
)
class ParentViewSet(viewsets.ModelViewSet):
serializer_class = ParentSerializer
queryset = ParentModel.objects.all()
class ChildViewSet(viewsets.ModelViewSet):
serializer_class = ChildSerializer
def get_queryset(self):
user = self.request.user
return ChildModel.objects.filter(created_by=user)
I would like for ParentSerializer.children
to only include the ChildModel
objects with created_by
as self.request.user
.
What is the correct way to filter ParentSerializer.children
to the current user?
I am open to changing the models as well.
CodePudding user response:
First i think you got a n 1 issue with your code.
When DRF will serialize ParentModel, accessing current_parent.children.all()
will produce an SQL query for each parent.
To prevent this you can use prefetch_related
class ParentViewSet(viewsets.ModelViewSet):
serializer_class = ParentSerializer
queryset = ParentModel.objects.prefetch_related(Prefetch("children"))
This will result in 2 SQL queries instead of N 1 (with N being the number of ParentModel row).
Additionnaly you can use prefetch_related
to filter the related model:
class ParentViewSet(viewsets.ModelViewSet):
serializer_class = ParentSerializer
def get_queryset(self):
user = self.request.user
return ParentModel.objects.prefetch_related(Prefetch("children", queryset=ChildrenModel.objects.filter(created_by=user)))
Which is what you are looking for i think