django中自定义分页和组合搜索组件

目录

1、分页组件

2、组合搜索组件


1、分页组件

example

"""
v1版本
    在视图函数:
        def customer_list(request):
            # 所有数据
            queryset = models.Customer.objects.filter(active=1).select_related('level')

            pager = Pagination(request, queryset)
            context = {
                "queryset": queryset[pager.start:pager.end],
                "pager_string": obj.html()
            }
            return render(request, 'customer_list.html', context)

    在页面上:
        {% for row in queryset %}
            {{row.id}}
        {% endfor %}

        <ul class="pagination">
            {{ pager_string }}
        </ul>

v2版本
    在视图函数:
        def customer_list(request):
            # 所有数据
            queryset = models.Customer.objects.filter(active=1).select_related('level')

            pager = Pagination(request, queryset)
            return render(request, 'customer_list.html', {"pager":pager})

    在页面上:
        {% for row in pager.queryset %}
            {{row.id}}
        {% endfor %}

        <ul class="pagination">
            {{ pager.html }}
        </ul>

"""


from django.utils.safestring import mark_safe  #(将生成html在前端展示)
import copy

class Pagination(object):
    """分页功能 ,
        <nav aria-label="Page navigation">
        <ul class="pagination">
            {{ paging_str }}
        </ul>
    </nav>"""

    def __init__(self, request, query_set, pages_num=10):
        self.query_dict=copy.deepcopy(request.GET)
#深拷贝,不会干扰原数据request.GET,self.query_dict.urlencode()获取当前请求的条件
#一定是get请求才会保留之前的参数条件,进而实现分页效果
        self.query_dict._mutable = True
        self.query_set = query_set
        self.cus_count = query_set.count()
        sum_pages, div = divmod(self.cus_count, pages_num)
        if div:
            sum_pages += 1
        self.sum_pages = sum_pages
        current_page = request.GET.get("page")
        if not current_page:
            current_page = 1
        else:
            if not current_page.isdecimal():
                current_page = 1
            else:
                # 解决页数小于0和大于最大值,方法1
                current_page = int(current_page)
                if current_page <= 0:
                    current_page = 1
                else:
                    # 解决页数小于0和大于最大值,方法1
                    if current_page >= self.sum_pages:
                        current_page = self.sum_pages
        self.current_page = current_page
        self.start = (self.current_page - 1) * pages_num
        self.end = self.current_page * pages_num

    def html(self):
            """生成分页的html页面"""
        if not self.sum_pages:
            """没有数据时,不显示分页内容"""
            return ""
        if self.sum_pages <= 11:
            start_page = 1
            end_page = self.sum_pages
        else:
            if self.current_page - 5 < 0:
                start_page = 1
                end_page = 11
            else:
                if self.current_page + 5 >= self.sum_pages:
                    end_page = self.sum_pages
                    start_page = self.sum_pages - 10
                else:
                    end_page = self.current_page + 5
                    start_page = self.current_page - 5

        # 解决页数小于0和大于最大值,方法2
        paging_list = []
        self.query_dict.setlist("page",["1"])
        paging_list.append("<li><a href='?{}'>首页</a></li>".format(self.query_dict.urlencode()))
        if self.current_page > 1:
            self.query_dict.setlist("page", ["{}".format(self.current_page - 1)])
            paging_list.append("<li><a href='?{}'><<</a></li>".format(self.query_dict.urlencode()))
        for i in range(start_page, end_page + 1):
            if i == self.current_page:
                self.query_dict.setlist("page", ["{}".format(self.current_page)])
                paging_list.append("<li><a class='active' href='?{}'>{}</a></li>".format(self.query_dict.urlencode(), i))
            else:
                self.query_dict.setlist("page", ["{}".format(i)])
                paging_list.append("<li><a href='?{}'>{}</a></li>".format(self.query_dict.urlencode(), i))
        if self.current_page < self.sum_pages:
            self.query_dict.setlist("page",["{}".format(self.current_page + 1)])
            paging_list.append("<li><a href='?{}'>>></a></li>".format(self.query_dict.urlencode()))
        self.query_dict.setlist("page", ["{}".format(self.sum_pages)])
        paging_list.append("<li><a href='?{}'>尾页</a></li>".format(self.query_dict.urlencode()))
        # 展示总条数
        paging_list.append(
            "<li class='disabled'><a >共计{}页{}条</a></li>".format(self.sum_pages, self.cus_count))
        paging_str = mark_safe("".join(paging_list))
        return paging_str

    def queryset(self):
        """返回query_set"""
        if self.cus_count:
            return self.query_set[self.start:self.end]
        return self.query_set

2、组合搜索组件

#!/usr/bin/env python
# -*- coding:utf-8 -*-

"""
    # 第一步:配置和传参
    from utils.group import NbSearchGroup, Option
    search_group = NbSearchGroup(request, models.Order, Option("status", is_multi=True))

    # 第二步:获取条件 .filter(**search_group.get_condition)
    order_query_set = models.Order.objects.filter(active=1).filter(**search_group.get_condition)

    # 第三步:数据传到前端
    return render(request, "order/order_list.html", locals())

    #前端页面展示

    1、css样式
    .search-group {
    padding: 5px 10px;
}

.search-group .row .whole {
    width: 60px;
    float: left;
    display: inline-block;
    padding: 5px 0 5px 8px;
    margin: 3px;
    font-weight: bold;
    text-align: right;

}

.search-group .row .others {
    padding-left: 80px;
}

.search-group .row a {
    display: inline-block;
    padding: 5px 8px;
    margin: 3px;
    border: 1px solid #d4d4d4;

}

.search-group .row a {
    display: inline-block;
    padding: 5px 8px;
    margin: 3px;
    border: 1px solid #d4d4d4;
}

.search-group a.active {
    color: #fff;
    background-color: #337ab7;
    border-color: #2e6da4;
}

    2、引入css样式
    <link rel="stylesheet" href="{% static "css/search-group.css" %}">

    3、前端页面调用展示
    {% if search_group.get_row_list %}  #获取前端页面
        <div class="panel panel-default">
            <div class="panel-heading">
                <i class="fa fa-filter" aria-hidden="true"></i> 快速筛选
            </div>
            <div class="panel-body">
                <div class="search-group">
                    {% for row in search_group.get_row_list %}
                        <div class="row">
                            {% for obj in row %}
                                {{ obj|safe }}
                            {% endfor %}
                        </div>
                    {% endfor %}
                </div>
            </div>
        </div>
    {% endif %}

"""
from django.db.models import ForeignKey, ManyToManyField


class SearchGroupRow(object):
    def __init__(self, title, queryset_or_tuple, option, query_dict):
        """
        :param title: 组合搜索的列名称
        :param queryset_or_tuple: 组合搜索关联获取到的数据
        :param option: 配置
        :param query_dict: request.GET
        """
        self.title = title
        self.queryset_or_tuple = queryset_or_tuple
        self.option = option
        self.query_dict = query_dict

    def __iter__(self):
        yield '<div class="whole">'
        yield self.title
        yield '</div>'
        yield '<div class="others">'
        total_query_dict = self.query_dict.copy()
        total_query_dict._mutable = True

        origin_value_list = self.query_dict.getlist(self.option.field)
        if not origin_value_list:
            yield "<a class='active' href='?%s'>全部</a>" % total_query_dict.urlencode()
        else:
            total_query_dict.pop(self.option.field)
            yield "<a href='?%s'>全部</a>" % total_query_dict.urlencode()

        for item in self.queryset_or_tuple:
            text = self.option.get_text(item)
            value = str(self.option.get_value(item))
            query_dict = self.query_dict.copy()
            query_dict._mutable = True

            if not self.option.is_multi:
                query_dict[self.option.field] = value
                if value in origin_value_list:
                    query_dict.pop(self.option.field)
                    yield "<a class='active' href='?%s'>%s</a>" % (query_dict.urlencode(), text)
                else:
                    yield "<a href='?%s'>%s</a>" % (query_dict.urlencode(), text)
            else:
                # {'gender':['1','2']}
                multi_value_list = query_dict.getlist(self.option.field)
                if value in multi_value_list:
                    multi_value_list.remove(value)
                    query_dict.setlist(self.option.field, multi_value_list)
                    yield "<a class='active' href='?%s'>%s</a>" % (query_dict.urlencode(), text)
                else:
                    multi_value_list.append(value)
                    query_dict.setlist(self.option.field, multi_value_list)
                    yield "<a href='?%s'>%s</a>" % (query_dict.urlencode(), text)

        yield '</div>'


class Option(object):
    def __init__(self, field, is_condition=True, is_multi=False, db_condition=None, text_func=None, value_func=None):
        """
        :param field: 组合搜索关联的字段
        :param is_multi: 是否支持多选
        :param db_condition: 数据库关联查询时的条件
        :param text_func: 此函数用于显示组合搜索按钮页面文本
        :param value_func: 此函数用于显示组合搜索按钮值
        """
        self.field = field
        self.is_condition = is_condition
        self.is_multi = is_multi
        if not db_condition:
            db_condition = {}
        self.db_condition = db_condition
        self.text_func = text_func
        self.value_func = value_func

        self.is_choice = False

    def get_db_condition(self, request, *args, **kwargs):
        return self.db_condition

    def get_queryset_or_tuple(self, model_class, request, *args, **kwargs):
        """
        根据字段去获取数据库关联的数据
        :return:
        """
        # 根据gender或depart字符串,去自己对应的Model类中找到 字段对象
        field_object = model_class._meta.get_field(self.field)
        title = field_object.verbose_name
        # 获取关联数据
        if isinstance(field_object, ForeignKey) or isinstance(field_object, ManyToManyField):
            # FK和M2M,应该去获取其关联表中的数据: QuerySet
            db_condition = self.get_db_condition(request, *args, **kwargs)
            return SearchGroupRow(title,
                                  field_object.remote_field.model.objects.filter(**db_condition),
                                  self,
                                  request.GET)
        else:
            # 获取choice中的数据:元组
            self.is_choice = True
            return SearchGroupRow(title, field_object.choices, self, request.GET)

    def get_text(self, field_object):
        """
        获取文本函数
        :param field_object:
        :return:
        """
        if self.text_func:
            return self.text_func(field_object)

        if self.is_choice:
            return field_object[1]

        return str(field_object)

    def get_value(self, field_object):
        if self.value_func:
            return self.value_func(field_object)

        if self.is_choice:
            return field_object[0]

        return field_object.pk

    def get_search_condition(self, request):
        if not self.is_condition:
            return None
        if self.is_multi:
            values_list = request.GET.getlist(self.field)  # tags=[1,2]
            if not values_list:
                return None
            return '%s__in' % self.field, values_list
        else:
            value = request.GET.get(self.field)  # tags=[1,2]
            if not value:
                return None
            return self.field, value


class NbSearchGroup(object):
    def __init__(self, request, model_class, *options):
        self.request = request
        self.model_class = model_class
        self.options = options

    def get_row_list(self):
        row_list = []
        for option_object in self.options:
            row = option_object.get_queryset_or_tuple(self.model_class, self.request)
            row_list.append(row)
        return row_list

    @property
    def get_condition(self):
        """
        获取组合搜索的条件
        :param request:
        :return:
        """
        condition = {}
        # ?depart=1&gender=2&page=123&q=999
        for option in self.options:
            key_and_value = option.get_search_condition(self.request)
            if not key_and_value:
                continue
            key, value = key_and_value
            condition[key] = value

        return condition

实现思路:参考kaifabj 中9、组合搜索,或则day11

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值