Django搭建网络相册:分页
3474 views, 2021/08/12 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 吐槽?评论区见!