目录
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