08 用Django分页器实现文章分页

本文介绍如何在Django项目中实现数据分页及本地图片上传功能,包括使用Django内置分页器Paginator进行数据分页处理,以及在模型中增加图片上传字段并在视图与模板中正确展示。

1、概述

Django有自带的分页器,可以将数据分在不同的页面中,并提供一些属性和方法实现对分页数据的操作。分页功能的类位于django/core/paginator.py中。

2、数据准备

在具体实现分类器功能前,首先准备一页网页类似与豆瓣电影展示。网页中的主要数据是图片,主题,内容等。其数据表格式类型如下:

class Video(models.Model):
    title = models.CharField(null=True, blank=True, max_length=300)
    content = models.TextField(null=True, blank=True)
    url_image = models.URLField(null=True, blank=True)
    editors_choice = models.BooleanField(default=False)
    def __str__(self):
        return self.title
对应部分网页显示如下,其中网页中带有分页按钮:

django后台数据结构如下:


3、使用Django分页器

1)在views.py层引入django的分页器,并通过(数据,页面数据个数)格式进行分页

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

def listing(request):
    context = {}
    vids_list = Video.objects.all()
    page_robot = Paginator(vids_list, 9) #每页显示9个数据
    try:
        vids_list = page_robot.page(request.GET.get('page'))
    except PageNotAnInteger: #判断页码是否为数值,如果不是,则返回第一页
        vids_list = page_robot.page(1)
    except EmptyPage: #判断是否为空页面,如果是,则返回最后一页
        vids_list =  page_robot.page(page_robot.num_pages)
    context['vids_list'] = vids_list
    return render(request, 'listing.html', context)

解析:

a、首先要引用django的分页器Paginator;

b、分页器使用的格式是有两个参数,第一个是进行分页的数据,第二个是显示每页的数据数量;

c、对网页的数据进行分页后,数据量都是有限的。因此在使用过程中可能会出现在网址中的数据页数大于分页数,则通过EmptyPage的异常来返回最后一页数据,

其中num_pages是分页器的属性,刚好返回最后一页的页码。

d、有可能你会在网址中输入非数值类型的页码,这样就不符合django分页器的设定。此时通过PageNotAnInteger异常捕获来返回第一页的数据。

2)同时在template模板层实现分页按钮的操作

<div class="ui pagination menu">
  {% if vids_list.has_previous %}
    <a href="?page={{ vids_list.previous_page_number }}" class="item">
        <i class="icon red left arrow"></i>
    </a>
  {% else %}
    <a href="?page={{ vids_list.start_index }}" class="item">
        <i class="icon left arrow"></i>
    </a>
  {% endif %}

  {% if vids_list.has_next %}
    <a href="?page={{ vids_list.next_page_number }}" class="item">
        <i class="icon red right arrow"></i>
    </a>
  {% else %}
    <a href="?page={{ vids_list.end_index }}" class="item">
        <i class="icon right arrow"></i>
    </a>
  {% endif %}
</div>
解析:

a、通过分页器操作的数据vids_list具有一些属性和方法,其中这边用到了has_previous/has_next来判断当前页是否有前一页/后一页;

b、如果当前页有has_previous,则通过previous_page_number属性来得到前一页的具体页码,可将链接返回到网址中;

c、如果当前页已经是首页(即has_previous返回为False),则通过start_index属性来得到第一条数据的索引即为1;

d、使用has_next的方法与has_previous操作类似。

4、实现后台图片的上传

1)在上述的例子中,网页的图片都是url格式存在url_image中的。要想实现在本地后台上传图片,首先需要在models.py层增加FileField字段

如下cover

class Video(models.Model):
    title = models.CharField(null=True, blank=True, max_length=300)
    content = models.TextField(null=True, blank=True)
    url_image = models.URLField(null=True, blank=True)
    editors_choice = models.BooleanField(default=False)
    cover = models.FileField(upload_to='cover_image', null=True) #该字段为增加的字段,类型为FileField,且上传的图片会保存到cover_image文件夹中
    def __str__(self):
        return self.title
2)在settings.py中设置upload文件路径


解析:

a、通过在settings.py中设定MEDIA_URL文件为箭头指向的upload,然后在MEDIA_ROOT中进行默认文件位置替换;

b、这样做的目的是将上传的图片等保存在本地文件夹中。

3)在urls.py中设定开发者使用模式

    from django.conf.urls.static import static

    if settings.DEBUG:
        urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
        urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
解析:在urls.py层增加如上代码,表明在本地开发时会引用本地的静态文件和MEDIA保存的文件,而在服务器上部署时会忽略。

4)修改模板层图片的显示

<div class="image">
  {% if vid.cover %}
    <img src="/upload/{{ vid.cover }}" alt="" style="height:200px;object-fit: cover;">
  {% else %}
    <img src="{{ vid.url_image }}" alt="" style="height:200px;object-fit: cover;">
  {% endif %}
</div>
解析:通过vid.cover判断,来实现不同图片的网页加载。如果cover字段存在,则引用upload/cover_image文件夹中的图片;如果不存在,则引用url_image字段图片。

5)在django后台进行操作

解析:在django后台中的cover字段处,会出现“选择文件”按钮,通过点击按钮选择相关图片,即可上传本地图片。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值