是否可以在Django中缓存整个页面?

时间:2019-06-20 22:43:54

标签: django django-cache

我目前正在this website工作。问题是页面需要3-4秒才能获得第一轮再见,我认为这是因为在页面中加载数据的查询非常慢。

在商店页面中,它基本上使用商店的对象来显示商店的基本信息,并使用ForeignKey关系来访问商店的图像。另外,它使用ManyToManyField访问商店的相似商店,这些商店也是商店对象。为了解决这个问题,我使用了prefetch_related和select_related,因此将许多重复查询的次数降至最低。但它仍然显示出较低的性能。

在那之后,我想可以通过缓存来改善它,所以我做了下面的事情。老实说,我对缓存的期望就像是超快速加载,因为它应该存储所有处理的查询,并仅显示请求的缓存中的数据。但是,老实说,它仍然显示3-4秒的加载性能。我是否以错误的方式使用缓存?

settings.py

...
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'django_cache',
    }
}
...

views.py

class StoreDetailView(View):
    def get(self, request, *args, **kwargs):
        store_domainKey = self.kwargs['store_domainKey']

        cache_store = 'store-{0}'.format(store_domainKey)
        store = cache.get(cache_store, None)
        if not store:
            try:
                q = (
                    Store.objects
                    .select_related('price_range')
                    .prefetch_related(
                        'top_keywords', 'sub_keywords', 'ship_to', 'likes',
                        'question_set', 'question_set__answer_set',
                        'similar_stores', 'sponsored_stores', 'image_set'
                    )
                    .get(domainKey=store_domainKey)
                )
            except Store.DoesNotExist:
                raise Http404
            cache.set(cache_store, q)
            store = cache.get(cache_store)


        cache_similar_stores = 'similar-stores-{0}'.format(store_domainKey)
        similar_stores = cache.get(cache_similar_stores, None)
        if not similar_stores:
            sponsored_stores_ids = sponsored_stores.values_list('sponsor_receiver__id', flat=True)
            q = (
                Similarity.objects
                .select_related('similar_store', 'similar_store__price_range')
                .prefetch_related('similar_store__image_set')
                .filter(similar_target=store)
                .exclude(Q(similar_store__id__in=sponsored_stores_ids) | Q(similar_store=store))
            )
            cache.set(cache_similar_stores, q)
            similar_stores = cache.get(cache_similar_stores)


        page = request.GET.get('page', 1)
        paginator = Paginator(similar_stores, 5)
        try:
            similar_stores = paginator.page(page)
        except PageNotAnInteger:
            similar_stores = paginator.page(1)
        except EmptyPage:
            similar_stores = paginator.page(paginator.num_pages)


        context = {
            'store': store,
            'sponsored_stores': sponsored_stores,
            'similar_stores': similar_stores,
            'top_3_similar_store_string': top_3_similar_store_string,
        }


        return render(request, template, context)

1 个答案:

答案 0 :(得分:1)

上面关于概要分析的评论绝对值得考虑,但是为了回答这个问题,我通常使用mixin缓存基于通用类的视图。例如:

from django.views.decorators.cache import cache_page
from django.views.generic import View

class CacheMixin(object):
    cache_timeout = 3600 * 24 * 7

    def get_cache_timeout(self):
        return self.cache_timeout

    def dispatch(self, *args, **kwargs):
        return cache_page(self.get_cache_timeout())(super().dispatch)(*args, **kwargs)

class StoreDetailView(CacheMixin, View):
    def get(self, request, *args, **kwargs):
    ...

您还可以使用片段缓存在模板级别进行缓存,但是必须小心考虑上下文中的任何变量作为模板片段标识符的一部分。

Django Debug Toolbar在识别有问题的查询及其来源方面非常有帮助。

祝你好运!