Django:即使使用缓存中的数据,模板加载速度也很慢
Django: template loading slowly even using data from cache
我有一个托管在 heroku 上的 django 应用程序,我有一个 'family album' 页面加载了一堆图像缩略图 link 到更大的图像详细信息页面。 (每个用户的图片集可能不同)。
这些缩略图中的每一个都使用一个 image_link.html 模板。在家庭相册页面上最多可以有大约 1100 个这样的缩略图,并且它在生产中加载了 peachy。
问题:现在我添加了一个小的悬停叠加层(从 w3schools here 中获取),这样当您将鼠标悬停在缩略图上时,您可以看到图片包含谁的叠加层。此列表由 Image 上的方法返回 class- 它不是属性,因此不会与 Image 对象一起返回。
添加这个使得模板加载速度非常慢:本地 4-5 秒,生产环境大约 22 秒(Heroku,使用 1 个专业的 Dyno)。我认为通常这种事情会通过分页变得更好,但在这种情况下我喜欢有一个长页面。 (虽然我可以先加载顶部,然后再填充其余部分)。
所以我做了一些事情:
- 在 views.py 中添加了一个 'get_image_index_data' 函数来循环,获取 pictured_list 结果,用我需要的内容创建一个数组,然后缓存它。我在接收器函数中调用它(侦听用户登录的信号),因此它将在用户单击家庭相册 link 时设置,并且 views.py 从缓存中获取它
- 我在家庭相册页面添加了模板片段缓存
问题:即使缓存了数据(我确认没有遗漏),加载速度仍然很慢(直到模板片段缓存启动?正在调查... )
代码如下:
我有一个调用此代码来保存数据的接收器函数:
def get_image_index_data(accessible_branches, profile):
image_list = Image.objects.none()
for branch in accessible_branches:
name = branch.display_name
image_list = image_list.union(Image.objects.filter(branches__display_name__contains=name).order_by('year'))
sorted_list = image_list.order_by('year')
# Save time on Family album page (aka image_index) by calling ahead for pictured_list. Elsewhere the template will retrieve it
family_album_data = []
for image in sorted_list:
family_album_data.append([image, image.pictured_list])
image_cache_name = 'images_' + str(profile.user)
cache.set(image_cache_name, family_album_data, 60 * 30) # save this for 30 minutes
return family_album_data
然后是渲染家庭相册的函数:
@login_required(login_url=login_url)
def image_index(request):
profile = get_display_profile(request).first()
accessible_branches = get_valid_branches(request)
image_cache_name = 'images_' + str(profile.user)
family_album_data = cache.get(image_cache_name)
if not family_album_data:
family_album_data = get_image_index_data(accessible_branches, profile)
context = {'image_list': family_album_data, 'accessible_branches': accessible_branches, 'branch2_name': branch2_name,
'profile': profile, 'user_person': profile.person, 'media_server': media_server, 'user': profile.user}
return render(request, 'familytree/image_index.html', context)
这是家庭相册模板 (image_index.html):
{% extends 'familytree/base.html' %}
{% block title %} - family album{% endblock title %}
{% block content %}
{% load cache %}
{% cache 1800 album profile %}
<h1>Family Album</h1>
{% if image_list %}
{% for image in image_list %}
{% include "familytree/image_link.html" with image=image height=150 show_hover=True pictured_list=pictured_list%}
{% endfor %}
{% else %}
<p>No images are available.</p>
{% endif %}
{% endcache %}
{% endblock content %}
image_link.html(新位是'if show_hover'块中的overlay span):
<div style="display: inline-block; margin-bottom:10px"; class="image_container">
<a href="{% url 'image_detail' image.id %}">
{% if image.little_name %}
<img src="{{ media_server }}/image/upload/h_{{ height }},r_20/{{ image.little_name }}" class="image"/>
{% else %}
<img src="{{ media_server }}/image/upload/h_{{ height }},r_20/{{ image.big_name }}" class="image"/>
{% endif %}
{% if show_hover %}
<span class="overlay">
<span class="text">Pictured: {{pictured_list}}</span>
</span>
{% endif %}
<div style="padding-left: 8px">
{% if image.year %}
({{ image.year }})
{% endif %}
</div>
</a>
</div>
一些建议:
- 委托在后台进程处理程序上构建的缓存,例如
celery
- 如果你想显示一个长页面,看看做一个类似 facebook 的无限滚动分页,给人一种你有一个长页面但仍在后台分页的错觉。
我有一个托管在 heroku 上的 django 应用程序,我有一个 'family album' 页面加载了一堆图像缩略图 link 到更大的图像详细信息页面。 (每个用户的图片集可能不同)。
这些缩略图中的每一个都使用一个 image_link.html 模板。在家庭相册页面上最多可以有大约 1100 个这样的缩略图,并且它在生产中加载了 peachy。
问题:现在我添加了一个小的悬停叠加层(从 w3schools here 中获取),这样当您将鼠标悬停在缩略图上时,您可以看到图片包含谁的叠加层。此列表由 Image 上的方法返回 class- 它不是属性,因此不会与 Image 对象一起返回。
添加这个使得模板加载速度非常慢:本地 4-5 秒,生产环境大约 22 秒(Heroku,使用 1 个专业的 Dyno)。我认为通常这种事情会通过分页变得更好,但在这种情况下我喜欢有一个长页面。 (虽然我可以先加载顶部,然后再填充其余部分)。
所以我做了一些事情:
- 在 views.py 中添加了一个 'get_image_index_data' 函数来循环,获取 pictured_list 结果,用我需要的内容创建一个数组,然后缓存它。我在接收器函数中调用它(侦听用户登录的信号),因此它将在用户单击家庭相册 link 时设置,并且 views.py 从缓存中获取它
- 我在家庭相册页面添加了模板片段缓存
问题:即使缓存了数据(我确认没有遗漏),加载速度仍然很慢(直到模板片段缓存启动?正在调查... )
代码如下:
我有一个调用此代码来保存数据的接收器函数:
def get_image_index_data(accessible_branches, profile):
image_list = Image.objects.none()
for branch in accessible_branches:
name = branch.display_name
image_list = image_list.union(Image.objects.filter(branches__display_name__contains=name).order_by('year'))
sorted_list = image_list.order_by('year')
# Save time on Family album page (aka image_index) by calling ahead for pictured_list. Elsewhere the template will retrieve it
family_album_data = []
for image in sorted_list:
family_album_data.append([image, image.pictured_list])
image_cache_name = 'images_' + str(profile.user)
cache.set(image_cache_name, family_album_data, 60 * 30) # save this for 30 minutes
return family_album_data
然后是渲染家庭相册的函数:
@login_required(login_url=login_url)
def image_index(request):
profile = get_display_profile(request).first()
accessible_branches = get_valid_branches(request)
image_cache_name = 'images_' + str(profile.user)
family_album_data = cache.get(image_cache_name)
if not family_album_data:
family_album_data = get_image_index_data(accessible_branches, profile)
context = {'image_list': family_album_data, 'accessible_branches': accessible_branches, 'branch2_name': branch2_name,
'profile': profile, 'user_person': profile.person, 'media_server': media_server, 'user': profile.user}
return render(request, 'familytree/image_index.html', context)
这是家庭相册模板 (image_index.html):
{% extends 'familytree/base.html' %}
{% block title %} - family album{% endblock title %}
{% block content %}
{% load cache %}
{% cache 1800 album profile %}
<h1>Family Album</h1>
{% if image_list %}
{% for image in image_list %}
{% include "familytree/image_link.html" with image=image height=150 show_hover=True pictured_list=pictured_list%}
{% endfor %}
{% else %}
<p>No images are available.</p>
{% endif %}
{% endcache %}
{% endblock content %}
image_link.html(新位是'if show_hover'块中的overlay span):
<div style="display: inline-block; margin-bottom:10px"; class="image_container">
<a href="{% url 'image_detail' image.id %}">
{% if image.little_name %}
<img src="{{ media_server }}/image/upload/h_{{ height }},r_20/{{ image.little_name }}" class="image"/>
{% else %}
<img src="{{ media_server }}/image/upload/h_{{ height }},r_20/{{ image.big_name }}" class="image"/>
{% endif %}
{% if show_hover %}
<span class="overlay">
<span class="text">Pictured: {{pictured_list}}</span>
</span>
{% endif %}
<div style="padding-left: 8px">
{% if image.year %}
({{ image.year }})
{% endif %}
</div>
</a>
</div>
一些建议:
- 委托在后台进程处理程序上构建的缓存,例如
celery
- 如果你想显示一个长页面,看看做一个类似 facebook 的无限滚动分页,给人一种你有一个长页面但仍在后台分页的错觉。