Django搭建网络相册:分页
3786 views, 2023/10/17 updated Go to Comments
正如你想得那样,分页作为一个通用功能,Django 也提供了内置的实现。
Django 把程序员照顾得太好了,严重缩短了大家的工时。
不996怎么升职加薪?
分页器
内置的分页器功能足够强大,配合模型用起来也是极其简单。
修改 views.py
文件:
# /photo/views.py
...
from django.core.paginator import Paginator
def home(request):
# 已有代码
photos = Photo.objects.all()
# 新增分页代码
paginator = Paginator(photos, 5)
page_number = request.GET.get('page')
paged_photos = paginator.get_page(page_number)
# 将分页器对象传入上下文
context = {'photos': paged_photos}
# 后续其他已有代码
...
...
你可以看到为了使用分页器,总共修改了四行代码(除去引入模块的语句)。从函数的第二行开始:
- 将模型的查询集
photos
、以及你期望的每页的图片数量作为参数,实例化分页器Paginator
。 - 从 GET 请求体中获取页码。
- 根据页码,从分页器中取得对应页码的对象。
- 将分页后的对象传递到模板。
欧了,改前端去。
前端代码
如果你觉得分页器仅仅是将列表做了个切片,那就错了。分页后的数据不仅具有原始查询集(queryset)的迭代功能,还包括了很多分页相关的元数据。
修改 list.html
模板,你就能看出来:
<!-- /templates/photo/list.html -->
...
{% block content %}
<div class="container py-2">
<!-- 已有代码 -->
<div class="row" data-masonry='{"percentPosition": true}'>
{% for photo in photos %}
...
{% endfor %}
</div>
<!-- 新增代码 -->
<div class="row justify-content-center py-5">
<span class="step-links paginator">
{% if photos.has_previous %}
<a
href="?page=1"
class="paginator prevnext" >
«
</a>
<a
href="?page={{ photos.previous_page_number }}"
class="paginator prevnext">
{{ photos.previous_page_number }}
</a>
{% endif %}
<span class="current">
{{ photos.number }}
</span>
{% if photos.has_next %}
<a
href="?page={{ photos.next_page_number }}"
class="paginator prevnext">
{{ photos.next_page_number }}
</a>
<a
href="?page={{ photos.paginator.num_pages }}"
class="paginator prevnext">
»
</a>
{% endif %}
</span>
</div>
</div>
...
{% endblock content %}
<!-- 新增代码 -->
{% block scripts %}
<style>
.paginator {
color: white;
text-align: center;
text-decoration: none;
}
.prevnext {
font-size: x-large;
}
.current {
font-size: xx-large;
padding-left: 10px;
padding-right: 10px;
}
</style>
{% endblock scripts %}
最主要的改动,就是在页面的底部增加了切换页码的入口。
需要注意的点:
- 分页后的对象
photos
拥有previous_page_number
、number
、has_previous
等一系列有关分页的属性,非常方便。(具体作用看属性名就能懂) - 超链接用
href="?page={{ photos.next_page_number }}"
给 GET 请求附加了数据,它在后端中通过request.GET.get('page')
被获取到。 - 代码末尾用 css 稍微修改了页码的颜色、文字大小等样式。(
.current
对应class="current"
的元素)
又欧了,测试去。
测试
刷新页面看看:
页面底部已经有页码可供选择了。
切换它们,并注意观察浏览器地址栏的变化。
总结
经过几章节的开发,项目的核心功能都具备了:列表、详情、数据存储、批量上传、登录、分页样样不少。
看似真的可以拿去称霸朋友圈了,但还是那个最致命的问题没解决:个人服务器的带宽太有限了,根本支撑不起高清图片的流量。或许可以通过缩略图等手段缓解首页的卡顿,但是细节展示你总要高清大图吧,治标不治本。
解决此问题除了选择更大的带宽外,还可以通过CDN加速、负载均衡、对象存储等手段。
下一章我们将探讨其中一种方案:对象存储(云存储)。
点赞 or 吐槽?评论区见!