高级视图_ListView类视图

本文详细介绍了Django中的ListView类视图,用于快速实现列表数据展示。内容包括ListView的属性如page_kwarg和get_queryset,以及分页操作涉及的Paginator和Page类。文章通过实例展示了如何使用ListView进行数据查询、分页处理,并讨论了前端翻页的实现方式。
摘要由CSDN通过智能技术生成

ListView类视图

1、在网站开发中,经常会出现需要列出某个表中的一些数据作为列表展示出来.比如文章列表,图书列表等等。在Django中可以使用ListView类视图来帮我们快速实现这种需求

2、即:如果需要在模板中以列表的形式展示一些数据,那么就可以使用ListView类视图来快速实现

3、ListView类视图跟前面介绍的View类视图和TemplateView类视图一样,都是为了方便我们快速实现某些特定功能的类视图
    ⑴这些类视图jango已经封装好了的,我们只需要继承对应的类以及重写某些属性和方法就可以了

例1:
⑴编辑视图

⑵编辑模板

⑶查看数据库数据

⑷访问第一页

⑸访问第二页

注:
1、上面例子中我们只是很简单的写了一个类视图,并继承于ListView类视图,就很容易的实现了一个列表显示页面
    ⑴在从数据库获取数据时,我们并没有使用SQL语句进行查询,只是提供了一个模型名,但成功的从对应表中查询出了数据
    ⑵在数据显示方面,我们只是定义了一个URL,但是可以通过查询字符串的方式来访问第二页的数据
    ⑶可以看出:有很多东西都是Django封装好了的,我们只需要按照我们的需要来传入对应的属性(方法)值就可以了
    ⑷模板在ListView类视图中是没有封装的,这个是完全需要我们自己来写的:相当于就是Django已经给你封装好了数据分页的视图了,我们要做的就是定义好传递给模板的参数以及模板

2、上面例子只是一个很简单的ListView类视图,主要是先熟悉下这个类视图里面有哪些东西

3、这个例子中:翻页功能我们是通过手动在地址栏中输入URL实现的。实际中应该是有个翻页按钮之类的,通过这个翻页按钮来向后端传递这个查询字符串参数值的

4、这个例子中:数据库中一共有四条数据,每页显示2条,那么总共有2页。我们如果让page=3的话,就会找不到页面。如果我们在网址后面没有传递page参数,默认返回的就是第一页。

 

 

ListView类视图属性、方法

属性、方法名描述
model   重写model类属性,指定这个列表是给哪个模型的
template_name指定这个列表的模板
paginate_by指定这个列表一页中展示多少条数据
context_object_name 指定这个列表模型在模板中的参数名称(传递到模板的参数名:键名)
ordering指定这个列表的排序方式
page_kwarg   获取第几页的数据的参数名称。默认是page
get_context_data获取上下文的数据
get_queryset根据需要来查询数据,默认是全部数据(all方法)

            
page_kwarg属性

1、page_kwarg属性值用来来修改查询字符串参数的参数名

2、这些属性可以理解为Python中的类属性:整个类公用的属性

例2:修改URL中页数参数名
⑴编辑视图

⑵访问第一页

⑶访问第二页

注:
1、可以通过"page_kwarg"属性值来修改查询字符串参数的参数名

2、URL中的查询字符串参数是不会影响的URL匹配的:查询字符串参数只是用于视图函数获取参数的(根据参数来返回对应的内容)
    ⑴即使访问的URL中的查询字符串参数的参数名错误了,还是可以正常访问的,只是说访问的内容可能不是正确的
    ⑵比如,这个例子中访问第二页时,正确的URL是:http://127.0.0.1:8000/zh/index/?p=2,但是我们实际访问的是http://127.0.0.1:8000/zh/index/?page=2
    ⑶由于http://127.0.0.1:8000/zh/index/是正确的,可以正常访问(访问的额第一页),由于查询字符串参数名错了,视图函数中不能获取到对应的值。因此不管其值时多少,实际上访问的都是第一页
    


get_context_data方法

1、get_context_data方法用来:获取上下文的数据,并且可以添加自己的参数

2、前面的例子中我们直接是将从数据库中查询出来的数据,传递给了模板,这些数据我们也不知道具体是什么样子的
    ⑴因此可以使用get_context_data方法来打印这些数据(打印从数据库中查询到的数据,以及其他一些信息)
    ⑵并且也可以使用该方法来额外添加某些参数值

例3:获取上下文
⑴数据源

⑵编辑视图

注:

可以看到整个上下文数据是一个字典
    ⑴模型中的数据:其键名为"context_object_name"属性指定的值"books",其值就是查询数据组成的QuerySet对象
        ①因此要获取查询数据,就可以使用其键名(books)来获取
    ⑵自己添加的数据:直接以键值对的形式存在
        ①因此要获取添加的数据,就可以使用其键名来获取
    ⑶另外整个字典中还有些其他的键值对,比如Paginator类还是Page类(都是以键值对的形式存在的),这些后面介绍

⑶编辑模板

⑷编辑URL

⑸访问:第一页

⑹访问:第N页 

注:
1、输出结果里面包含了很多东西,有我们常用的paginator类、page_obj类和我们自定义的一些参数等。paginator类、page_obj类下面将会进行讲解

2、可以看到,其实上面有很多代码是我们自己没有写的,都是ListView视图类封装好了,我们只需要设置好对应属性的值和方法的值以及模板就好了。比如数据是如何分页的,如何去获取第N页的数据,这些都不是我们完成的

 

get_queryset方法

get_queryset:如果你提取数据的时候,并不是要把所有数据都返回,那么你可以重写这个方法。将一些不需要展示的数据给过滤掉

例4:
⑴编辑视图

⑵访问

注:
需要记住:这些Django内置的类视图只是帮你封装好了如何实现一些功能(视图),至于向前端传递哪些数据、数据如何在前端进行展示都是需要我们自己去定义的

 

 

Paginator和Page类

Django提供了数据分页的类,这些类被定义在django/core/paginator.py中
    ⑴对象Paginator用于对列进行一页n条数据的分页运算
    ⑵对象Page用于表示第m页的数据

 

paginator类对象的属性

属性名说明
conunt总共多少条数据
num_pages返回分页之后的总页数
page_range返回分页后页码的列表。比如有三页,那么就是range(1,4)

 

Paginator类对象的方法

方法名说明
page(self, number) 返回第number页的Page类实例对象

    
Page类对象的属性

属性名说明
number返回当前页的页码
start_index当前这一页的第一条数据的索引值
end_index当前这一页的最后一条数据的索引值
object_list返回包含当前页的数据的查询集
paginator 返回对应的Paginator类对象


Page类对象的方法

方法名说明
has_previous判断当前页是否有上一页
has_next  判断当前页是否有下一页
previous_page_number返回前一页的页码
next_page_number返回下一页的页码

注:
1、前面在介绍ListView类视图时,打印过向前端传递过去的上下文content。ListView类视图的content里面就包含了Paginator和Page类

2、因此,我们只需要使用Paginator和Page类中的类属性(方法)就可以实现更加完美是分页功能了

3、前面例子中,在请求第N页的数据时,采用的是直接手动在URL中输入"?pages=2"这样的参数。这在实际中肯定是不行的,一般都是通过前端点击第N页按钮后,前端自动获取当前页码然后自动添加到URL中并传递给服务器

例5:打印content
⑴查看ListView类视图返回

⑵目的

 

Paginator类属性

1、ListView类视图返回的是一个字典,因此可以直接使用字典方法来获取其中某个键的值:paginator类

2、获取到paginator类后,就可以使用其属性来获取对应的属性值了

3、Paginator类主要返回的是数据个数、分页条数的一些数据

例6:
⑴编辑视图

⑵数据库数据

 

Page类属性

1、ListView类视图返回的是一个字典,因此可以直接使用字典方法来获取其中某个键的值:Page类

2、获取到paginator类后,就可以使用其属性来获取对应的属性值了

3、Page类主要用于对当前所处页的一些信息

例7:
⑴编辑视图

⑵编辑模板

⑶访问:第一页

例7_1:
⑴编辑视图

注:
1、不管是Paginator类还是Page类:它们的属性值都是在重写后的get_context_data()中获取的

2、当然也可以在模板中直接获取:它们是跟着content一起传递给模板的,只是说其值类型是一个class(类)
    ⑴如果上下文中键的值是一个类对象的话,就需要使用:{{键名.属性名}}的方式来访问了

 

分页示例

这里介绍一个比较粗糙的分页示例

例8:
⑴编辑视图

⑵编辑模板

⑶编辑URL

⑷访问


 

 

拓展

对数据进行分页操作 

1、对数据进行分页操作的方法有很多,自己感觉还是前后端分离比较好
    ⑴前端请求时,向服务器传递当前请求的第n页与每页显示多少条数据,后端只需要将当前请求的那几条数据传递给前端就好了

2、至于后端如何根据前端传递来的"第n页与每页显示多少条数据"参数,去查询对应的数据的方法就有几种方法了
    ⑴使用LIMIT(Mysql中):通过在查询SQL语句中加入LIMIT关键字来达到返回部分数据的效果:这样直接查询出来的数据就是需要返回给前端的数据
    ⑵使用分片:使用SQL语句查询出全部符合条件的数据,这些数据是一个嵌套元组(列表),因此可以根据传入的参数来分片出对应的数据
    ⑶在对数据进行LIMIT或分片操作时,还可以使用ORDER BY来对数据进行排序(排序后使用LIMIT或分片)

例1:分片

import pymysql

db_conn = pymysql.connect(user="root",password="123456",host="localhost",database="zhouh",port=3306)

db_cursor = db_conn.cursor()
sql = """SELECT id,title,price,author FROM polls_article ORDER BY title"""

"""分页效果是没法在SQL语句中完成的,只能在代码中实现"""
def SelectResult(pageSize, currentPage):
    db_cursor.execute(sql)
    #先查询出所有数据
    selectResults = db_cursor.fetchall()
    total = len(selectResults)
    print("数据个数为:", len(selectResults))
    # 计算查询数据个数最多显示多少页:数据总条数除以每页显示条数
    PageInfo = divmod(total, pageSize)
    # 值小于0,表示total>pageSize,一页就能显示完,因此总页数为1
    if PageInfo[0] == 0:
        maxPage = 1
    else:
        # 有值且余数等于0,表示刚好显示完全,总页数为商
        if PageInfo[1] == 0:
            maxPage = PageInfo[0]
        # 有值且有余数(不为0),表示多出来了n条(n<5),总页数为商+1
        else:
            maxPage = PageInfo[0] + 1
    # 判断当前请求页是否存在:不存在
    if currentPage > maxPage or currentPage <= 0:
        data = {
            "total": total,
            "pageSize": pageSize,
            "currentPage": currentPage,
            "data": []}
        return data
    else:
        # 查询结果个数为0时
        if total == 0:
            data = {
                "total": total,
                "pageSize": pageSize,
                "currentPage": currentPage,
                "data": selectResults}
            return data

        # 查询结果个数大于0小于pageSize时:一次性全部返回
        elif 0 < total < pageSize:
            data = {
                "total": total,
                "pageSize": pageSize,
                "currentPage": currentPage,
                "data": selectResults}
            return data
        # 查询结果个数大于pageSize时:返回当前请求页的数据
        else:
            # 根据分片来返回当前页的数据
            start = (currentPage - 1) * pageSize
            end = currentPage * pageSize
            data = {
                "total": total,
                "pageSize": pageSize,
                "currentPage": currentPage,
                "data": selectResults[start:end]}
            return data


datas = SelectResult(5, 1)
print(datas)
for data in datas["data"]:
    print(data)

"""
#这段代码中最重要的就是:如何确定当前请求的是哪些数据(start变量值和end变量值),另外还有些判断,比如确定当前页面
数据个数为: 6
{'currentPage': 1, 'total': 6, 'data': ((8, 'ds', 123.0, '32'), (7, 'wed', 123.0, '32'), (2, '三国演义', 154.0, '罗贯中'), (4, '水浒传', 140.0, '施耐庵'), (3, '红楼梦', 141.0, '曹雪芹')), 'pageSize': 5}
(8, 'ds', 123.0, '32')
(7, 'wed', 123.0, '32')
(2, '三国演义', 154.0, '罗贯中')
(4, '水浒传', 140.0, '施耐庵')
(3, '红楼梦', 141.0, '曹雪芹')
"""


例1_1:LMIT

import pymysql

db_conn = pymysql.connect(user="root",password="123456",host="localhost",database="zhouh",port=3306)

db_cursor = db_conn.cursor()

def SelectResult(pageSize, currentPage):
    start = (currentPage - 1) * pageSize
    end = currentPage * pageSize
    sql = """SELECT id,title,price,author FROM polls_article ORDER BY  title  LIMIT %s,%s"""%(start,end)
    db_cursor.execute(sql)
    selectResults = db_cursor.fetchall()
    return selectResults

selectResults = SelectResult(5,1)
print(selectResults)

"""
实例LIMIT来查询数据的话,感觉就没法计算数据总条数和判断当前请求页实际是否存在了
((8, 'ds', 123.0, '32'), (7, 'wed', 123.0, '32'), (2, '三国演义', 154.0, '罗贯中'), (4, '水浒传', 140.0, '施耐庵'), (3, '红楼梦', 141.0, '曹雪芹'))
"""

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值