Andrew
Andrew

Reputation: 1575

How to cache query data per request

I have a decorator that fetches some data from DB and modifies response context data. This decorator is applied to several views, the problem is that every time the decorator function is being executed it makes the DB query again. I would like to cache the result of a DB only per request, on page refresh/new request I would like to fetch data again.

views.py

def set_data():

  def wrap(request):
   # fetching data from db
   data = get_some_data_from_db()
   response = view(request)
   response.context_data["data"] = data
   return response.render()

 return wrap


@set_data
def view1(request):
  context = {...}
  return TemplateResponse(request, "template1.httml", context)

@set_data
def view2(request):
  context = {...}
  return TemplateResponse(request, "template2.httml", context)

I've tried to use django-request-cache library, but this doesn't solve this problem.

ANy idea how can i achieve it?

Upvotes: 1

Views: 672

Answers (1)

SMoenig
SMoenig

Reputation: 514

Here's my suggestion using functools.lru_cache:

from functools import lru_cache

# definition of get_some_data_from_db
@lru_cache(max_size=None)
def get_some_data_from_db():
    # get from db code here...

def view1(request):
    context = {
        # returns cached result
        'data': get_some_data_from_db()  
    }
    # ...
    return TemplateResponse(request, "template1.html", context)


def view2(request):
    context = {
        # returns cached result
        'data': get_some_data_from_db()  
    }
    # ...
    return TemplateResponse(request, "template2.html", context)

def view_that_handles_form_submit(request):
    if request.method == 'POST':
       form = MyFormClass(request.POST)
       if form.is_valid():
           # save input
           form.save()
           # clear the cache 
           get_some_data_from_db.cache_clear()
           context = {
              'form': form,
              'data': get_some_data_from_db(),  # fills cache with new result
           }
    return TemplateResponse(request, "form_template.html", context)

Upvotes: 1

Related Questions