The part of my problem is solved by the question: #72534250
I understood that the path I was following was wrong, and I should change the optimization of the models to serializers and/or viewsets.
But how?
I had this structure:
*I already removed element_name
and element_text
from Models Foo
class User(models.Model):
name = models.CharField(max_lenth=50)
age = models.IntergerField()
class Customer(models.Model):
user = models.ForeingKey(User, on_delete=models.CASCADE, verbose_name='User')
class Element(models.Model):
name = models.CharField(max_lenth=50)
text = models.TextField()
class Bar(models.Model):
element = models.ForeingKey(Element, on_delete=models.CASCADE, verbose_name='Element')
class Foo(models.Model):
bar = models.OneToOneField(Bar, on_delete=models.CASCADE, verbose_name='Bar')
customer = models.ForeingField(Customer, on_delete=models.CASCADE, verbose_name='Customer')
is_active = models.BooleanField('Is Active', default=False)
def user(self):
return self.customer.user
# Removed
def element_name(self):
return self.bar.element.name
# Removed
def element_text(self):
return self.bar.element.text
And these serializers:
class UserSerializer(ModelSerializer):
class Meta:
model = User
fields = '__all__'
class CustomerSerializer(ModelSerializer):
class Meta:
model = Customer
fields = '__all__'
class ElementSerializer(ModelSerializer):
class Meta:
model = Element
fields = '__all__'
class BarSerializer(ModelSerializer):
element = ElementSerializer()
class Meta:
model = Bar
fields = '__all__'
class FooSerializer(ModelSerializer):
bar = BarSerializer()
user = UserSerializer()
class Meta:
model = Foo
fields = '__all__'
And this viewset:
class FooViewSet(ModelViewSet):
serializer_class = FooSerializer
permission_classes = [IsAuthenticated]
authentication_classes = [JWTAuthentication]
http_method_names = ['get', 'post', 'patch']
def get_queryset(self):
active = self.request.query_params.get('is_active', False)
name = self.request.query_params.get('name', '')
data = {'is_active': active}
if name == 'Fire':
data['bar__element__name'] = name
queryset = Foo.objects.filter(**data)
return queryset
I try this tutorial, but I didn't notice any real performance improvement. So I'm looking for another way to solve this problem.
I thought... If I just put select_related(...)
in the return of get_queryset
, how Django Rest would identify that it is to serialize the cached data? Would that really improve performance?
I also need element_name
, element_text
and object user
to be returned in the GET of FooViewSet
. How can I return them in the most efficient way?
how Django Rest would identify that it is to serialize the cached data? Would that really improve performance?
All the data that has been fetched by select_related
are in your model object instances. So since the serializers as well as the model properties you defined essentially use these instances, they will have access to this "cached" data directly.
I also need element_name, element_text and object user to be returned in the GET of FooViewSet. How can I return them in the most efficient way?
In line with this, you can get them all in one query (including what element_name
and element_text
needs) with:
queryset = Foo.objects.select_related(
"bar__element",
"customer__user",
).filter(**data)