Reputation: 678
I have two model, one for Question and two for answer
tow have a forginkey to one and one have a forginkey to users
for this purpose I use a To be grouped together at the same endpoint I add the second to the first in serializer
With this solution, Django accessed the database with the number of answers in the second form and I cannot use Select_related here
the question is, how can I reduce database hits to the second model
Models.py
class Consultation(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
create_at = models.DateTimeField(auto_now_add=True)
files = models.FileField(upload_to="media/files", null=True, blank=True,
validators=[FileExtensionValidator(['pdf', 'jpg', 'png'])])
def __str__(self):
return self.user.username
class Meta:
ordering = ['-create_at']
class ConsultaionAnswer(models.Model):
consultation = models.ForeignKey(
Consultation, on_delete=models.CASCADE, related_name='reply')
answer = models.TextField(null=True, blank=True)
def __str__(self):
return self.consultation.content[:20] + "..."
serializers.py
class ConsultaionAnswerSerilaizers(serializers.ModelSerializer):
class Meta:
model = ConsultaionAnswer
fields = ('answer',)
class ConsultationSerilaizers(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(
read_only=True,
default=serializers.CurrentUserDefault()
)
username = serializers.StringRelatedField(
source='user.username',
read_only=True,
)
reply = ConsultaionAnswerSerilaizers(read_only=True, many=True)
class Meta:
model = Consultation
fields = (
"id",
"user",
"content",
'create_at',
'files',
'username',
"reply"
)
views.py
class ConsultationView(APIView):
serializer_class = ConsultationSerilaizers
def get(self, request, format=None):
consultat = Consultation.objects.select_related().filter(user=request.user)
serializer = self.serializer_class(
consultat, many=True, context={'request': request})
return Response(serializer.data)
Upvotes: 1
Views: 691
Reputation: 525
This should works:
consultat = Consultation.objects.prefetch_related('reply').filter(user=request.user)
Since it is a one-to-many relation, you'll need a prefetch_related
instead (see this link). And you also need to specify which field(s) you want to prefetch as well.
prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using select_related,
Upvotes: 1