0

I have slow queries in my Django restframework project.

Many nested serializers are causing slow HTTP requests (2-5 seconds)

So I thought about using a cache that Django can provide with Memcache server.

But I'm afraid I don`t really understand its behavior. What happens if the client request the same query non-stop every 1 second, and suddenly one of the objects changed? Will the user get the cached results or will Django return the cached results with the specific change?

demongolem
  • 9,474
  • 36
  • 90
  • 105
Oz Bar-Shalom
  • 1,747
  • 1
  • 18
  • 33
  • First optimise your endpoints before caching. Did you optimise your db query? Use Django debug toolbar and `.select_related('some_relation')` to reduce db hits and speed up your endpoint. You can also split your serialisers in listing serialisers (minimal nested) and detail serialisers (all needed related objects). – allcaps May 18 '17 at 19:09
  • already did. The main list items query have to be detailed with nested serializers :( – Oz Bar-Shalom May 18 '17 at 19:11
  • So there are no duplicate queries in django debug toolbar? – allcaps May 18 '17 at 19:14
  • still, there is a work there. But my main question was about the cache. after I done with optimizing – Oz Bar-Shalom May 18 '17 at 19:15
  • Really, use cache as last resort. I never had to use it since proper use of select related did solve my issues with slow endpoints. Also you claim that many nested serialisers are necessary, but I do not believe that. Batching, multiple calls, multiple endpoints, etc are ways to keep the api fast. Yes, it requires some work on the client side, but no person or system needs all data all the time. – allcaps May 18 '17 at 19:32

1 Answers1

0

Django does not manage cached data automatically. You have to manage it yourself.

There are several approaches you can take to manage cached data based your whole application logic.

  • you can use django signals to track object changes

https://docs.djangoproject.com/en/1.11/ref/signals/#module-django.db.models.signals

  • you can override model's save and delete methods
def save(self, *args, **kwargs):
    super(MyModel, self).save(*args, **kwargs)
    cache.set(str(self.pk), pickle.dumps(self))
  • you can use DRF's generic views save and deletion hooks:

perform_create, perform_update and perform_delete methods

def perform_update(self, serializer):
    obj = serializer.save()
    cache.set(str(obj.pk), pickle.dumps(obj))

http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview

for api based apps I prefer using the generic view hooks.

zaphod100.10
  • 3,331
  • 24
  • 38