美文网首页
2020-05-08--Django项目7--orglist内容

2020-05-08--Django项目7--orglist内容

作者: program_white | 来源:发表于2020-05-09 20:11 被阅读0次

    Orglist.html中内容的分页

    问题描述:



    也就是当列表中数据项很多时,我们不可能把他全部写在一页上,所以要对它进行分页,用户点击那一页的页码,就显示该页的内容。

    1.分页组件-----django-pure-pagination

    GitHub网址:
    https://github.com/jamespacileo/django-pure-pagination

    在我们之前也讲过分页操作,使用django自带的分页,但是为了美观,我们要使用这个分页组件。这个组件进行分页时页码不会全部显示,之前的分页会显示全部页码,不好看:


    (1)安装组件
    pip install django-pure-pagination
    

    我们之前在requirments.txt中已经安装了该组件,所以这里无需下载。(我们每安装一个库或者组件都把它写到requirments.txt中,方便以后的项目部署)


    (2)注册组件

    在settings.pyz中的INSTALLED_APPS,添加一个:

    'pure_pagination'
    
    (3)分页组件的设置

    在settings.py中的最后加上:

    #分页组件相关的设置
    PAGINATION_SETTINGS = {
        'PAGE_RANGE_DISPLAYED': 10,  #主分页部分显示几个
        'MARGIN_PAGES_DISPLAYED': 2,  #省略号前边或后边显示几个
        'SHOW_FIRST_PAGE_WHEN_INVALID': True,  #是否显示第一页
    }
    

    2.编写view操作分页

    首先我们要分页,就不能在后端服务器中把所有的数据信息传给前台了,要先把数据分成若干部分,再传给前台html。

    class OrgView(View):
        def get(self,request,*args,**kwargs):
            '''
            展示授课机构的列表页
            :param request:
            :param args:
            :param kwargs:
            :return:
            '''
            all_orgs = CourseOrg.objects.all()         #查询所有的机构信息
            org_nums = all_orgs.count()          #查询机构的个数
            all_citys = City.objects.all()       #查询所有的城市信息
    
            #分页部分
            #获取page,如果没找到或者出错都置page为1
            try:
                page = request.GET.get('page', 1)
            except PageNotAnInteger:
                page = 1
    
            #参数1:作用对象,参数2:单页显示数量,参数3:request
            p = Paginator(all_orgs, per_page=5,request=request)
    
            orgs = p.page(page)          #获取page页的信息
    
    
            return render(request, 'orglist.html',{
                'all_orgs':orgs,
                'org_nums':org_nums,
                'all_citys':all_citys
                })
    

    解析:
    (1)首先检测一下错误信息,保证每个page都正常显示.
    (2)通过Paginator类实例化,对获取到的全部机构信息进行分割,每页5个
    (3)通过Paginator的实例对象(p)中的方法page(页码)获取该页码的内容信息,最后传给模板进行重新进行数据绑定。

    3.orglist.html列表信息分页显示的重构

    在上一步后台的视图函数把分好的每页的数据信息传给了orglist.html。
    当我们运行项目,点击进入到orglist.html时,会出现以下错误:



    Page对象不可被迭代。

    这是由于在服务器的view中,在没有分页的时候,我们传的是Queryset对象,可以被迭代(在orglist.html中我们使用for循环进行循环显示的),我们现在传值org为Page对象,不能被迭代。
    解决:
    在orglist.html修改for循环的循环对象:

    all_orgs   ----->   all_orgs.objects.list
    

    找到orglidst.html中的页码的html代码:
    他是一个无序列表

    <div class="pageturn">
                            <ul class="pagelist">
                                <li class="active"><a href="?page=1">1</a></li>
                                <li><a href="?page=2" class="page">2</a></li>
                                <li><a href="?page=3" class="page">3</a></li>
                                <li class="long"><a href="?page=2">下一页</a></li>
                            </ul>
                        </div>
    

    在ul标签下添加:

    {{ all_orgs.render }}
    

    把其他的li标签的页码注释了运行后:



    但是我们不用这个。哈哈!!
    我们使用的时分页组件django-pure-pagination提供的代码。
    但是要对它进行改造,改一些变量的名称。

     {% if page_obj.has_previous %}
            <a href="?{{ page_obj.previous_page_number.querystring }}" class="prev">&lsaquo;&lsaquo; {% trans "previous" %}</a>
        {% else %}
            <span class="disabled prev">&lsaquo;&lsaquo; {% trans "previous" %}</span>
        {% endif %}
        {% for page in page_obj.pages %}
            {% if page %}
                {% ifequal page page_obj.number %}
                    <span class="current page">{{ page }}</span>
                {% else %}
                    <a href="?{{ page.querystring }}" class="page">{{ page }}</a>
                {% endifequal %}
            {% else %}
                ...
            {% endif %}
        {% endfor %}
        {% if page_obj.has_next %}
            <a href="?{{ page_obj.next_page_number.querystring }}" class="next">{% trans "next" %} &rsaquo;&rsaquo;</a>
        {% else %}
            <span class="disabled next">{% trans "next" %} &rsaquo;&rsaquo;</span>
        {% endif %}
    

    我们要把这个组件提供的逻辑代码和orglist原有的页码显示代码进行结合:

    <ul class="pagelist">
                                {#   上一页   #}
                                {% if all_orgs.has_previous %}
                                    <li class="long"><a href="?{{ all_orgs.previous_page_number.querystring }}"
                                                        class="page">上一页</a></li>
                                {% endif %}
                                {#   页码循环    #}
                                {% for page in all_orgs.pages %}
                                    {% if page %}
                                        {% ifequal page all_orgs.number %}
                                            {# 用户点击的是否是当前页码 #}
                                            <li class="active"><a
                                                    href="?{{ page.querystring }}">{{ page }}</a>
                                            </li>
                                        {% else %}
                                            <li class="page"><a
                                                    href="?{{ page.querystring }}">{{ page }}</a>
                                            </li>
                                        {% endifequal %}
                                    {% else %}
                                        <li class="none">...</li>
                                    {% endif %}
                                {% endfor %}
    
                                {#  下一页   #}
                                {% if all_orgs.has_next %}
                                    <li class="long"><a href="?{{ all_orgs.next_page_number.querystring }}"
                                                        class="page">下一页</a></li>
                                {% endif %}
    
                            </ul>
    

    分析:分页的页码list分三部分:

    • 上一页
    • 页码列表
    • 下一页
      1.如果page对象有上一页,那麽就显示列表项--上一页,并且链接到上一页。并加上css样式class=“long”
      2.循环page对象的页码(pages),该页码存在(存在与否与settings中的设置有关),并且是用户点击的页码,那么就显示该循环项{{page}},并加上css样式class=“active”(加黑)。如果不是用户当前页,也显示,但是加上css样式class=“page”(不加黑)。
      页码不存在,那么就显示 ...。
      3.如果page对象有下一页,那麽就显示列表项--下一页,并且链接到下一页。并加上css样式class=“long”
      修改settings中的页码设置:
      主分页只显示3个页码,其他分区显示1个
    #分页组件相关的设置
    PAGINATION_SETTINGS = {
        'PAGE_RANGE_DISPLAYED': 3,  #主分页部分显示几个
        'MARGIN_PAGES_DISPLAYED': 1,  #省略号前边或后边显示几个
        'SHOW_FIRST_PAGE_WHEN_INVALID': True,  #是否显示第一页
    }
    

    orglist一共有6个数据,每页只显示1个
    运行效果图:



    这些内容及代码在github的分页组件上都有。

    机构类别筛选选项内容的实现

    当我们访问到orglist.html时,默认显示全部的,在实际开发中,会设置选项进行筛选内容,方便查找。
    我们首先找到该部分的html代码:



    查看接口为get请求,也就是说当用户点击某一个筛选选项时,其访问服务器的url后会加上该选项的信息。
    所以我们要在后端view视图中进行操作获取。
    打开apps/organizations/view.py:
    我们要把获取筛选信息的逻辑代码写在分页之前,查询数据库数据之后。因为分页是针对于即将要显示与前台的数据,所以用户筛选后的信息也一样要分页。

    #筛选选项--类别
            category = request.GET.get('ct','')    #获取前台接口数据
            if category:
                # 过滤类别为用户选择的数据
                all_orgs = all_orgs.filter(category=category)
    

    解析:使用GET方法进行获取前端传过来的数据,如果没有,默认'',如果该字段存在,那么使用ORM进行筛选并再赋给all_orgs,传给前台页面。
    运行:



    筛选完成。
    但是有一个小问题:当我们点击筛选选项时,高亮还是默认全部的选项。
    所以我们要在html页面做css样式的判断。
    高亮的css:



    解决:
    首先我们要判断用户点的是哪个按钮,唯一的辨识就是用户点击后传到后台的接口数据--category,所以在后台把该值传过来。

    在前台的css,要用做判断依据:

    <a href="?city="><span class="{% ifequal category ''%}active2{% endifequal %}">全部</span></a>
    <a href="?ct=pxjg&city="><span class="{% ifequal category 'pxjg'%}active2{% endifequal %}">培训机构</span></a>
    <a href="?ct=gx&city="><span class="{% ifequal category 'gx'%}active2{% endifequal %}">高校</span></a>
    <a href="?ct=gr&city="><span class="{% ifequal category 'gr'%}active2{% endifequal %}">个人</span></a>
    

    把传过来的category在于其点击时传给后台的接口值进行比较,如果相等,那么class=‘active2’显示。形成高亮。默认全部按钮高亮。
    运行:
    点击‘高校’:


    所在地区的筛选选项的实现

    1.地区的显示

    所在地区的显示相对于机构类别有所不同,他的选项是动态的,要从数据库中循环遍历显示。
    那么找到所在地区部分的html代码,对它进行for循环的改造:

    <div class="cont">
         <a href="?ct="><span class="active2">全部</span></a>
    
         {% for city in all_citys %}
              <a href="?city={{ city.id }}&ct="><span class="">{{ city.name }}</span></a>
        {% endfor %}
    </div>
    

    但是点击是没有什么效果的。

    2.编写地区筛选的视图逻辑

    当用户点击了某个地区以后,要显示相应的内容信息,就要对视图进行修改:
    在机构类别的筛选逻辑之后,添加以下代码:

     #对所在城市进行筛选
            city_id = request.GET.get('city','')          #获取前台用户点击的选项数据
            if city_id:             #如果存在,
                if city_id.isdigit():          #如果该数据合法,
                     all_orgs = all_orgs.filter(city_id=city_id)         #过滤用户选择的数据
    

    运行:
    点击所在地区的选项----沈阳市


    数据显示成功。
    但是出现了三个问题:

    • 1.机构数量的显示没有变化,一直显示的是所有的机构数量,没有根据相应的选项进行实时更新。
    • 2.当点击机构类别的选项后,再点击所在地区的选项,机构类别的选项重新刷新为全部,也就是说两种筛选选项没有联动起来,都是独立的。
    • 3.高亮的显示没有变换

    (1)机构数量实时更新。

    首先我们分析,之前我们从后台传递过来的数量一直都是所有的总数,所以我们要改变数量计算的位置,也就是在分页之前,经过两层过滤后的机构总数。

    #显示最后绑定到网页上的机构数量。
    org_nums = all_orgs.count()
    

    运行:
    点击培训机构后:


    筛选选项联动

    分析:

    选项没有联动的原因?
    我们查看前端的选项接口:ct和city。机构类别的city没有赋值,所在地区的ct没有赋值。
    现在想:当用户点击了机构类别选项后,再点击所在地区选项,要想联动的话,就要把点击机构类别ct的值传给所在地区选项的ct值,用户再点击所在地区的选项时,ct和city都有了值。反之,也是一个道理,先点击地区选项,就要把city.id传给机构类别选项的city,再点击时,也就有了两个值。

    解决:
    机构类别传给后台的值为category,那么把category从后台传给前台,再绑定到地区的ct值上。
    所在地区传给后台的值为city_id,那么把city_id从后台传给前台,但是city_id就是city.id,它本身就是动态的,(根据用户点击的选项不同city.id就不同)
    所以把city.id绑定到机构类别的city值上。



    也就是互绑。

    高亮

    相关文章

      网友评论

          本文标题:2020-05-08--Django项目7--orglist内容

          本文链接:https://www.haomeiwen.com/subject/hyoqnhtx.html