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

Is it possible cache the whole page in Django?

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

在商店页面中,它基本上是使用商店的对象来显示商店的基本信息,并使用外键关系来访问商店的图像。此外,它使用 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)

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

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 调试工具栏对于识别有问题的查询及其来源非常有帮助。

祝你好运!