- 关键字搜索。 可以做到的效果是, 输入20。 后太通过 Q()  函数。 来实现。  搜索是一个大的问题点。

-  要想实现组合搜索, 首先要 明确的一点是。 在我当前的页面上, 正在进行展示的是 那一张表的数据。
- 并且, 既然是搜索, 那么必然的一点就是。 我的搜索条件, 必须是 和 我这张表中的,字段由关系的。
  - 比如, UserInfo 表。 那么 名字就是一个 可以用作搜索的字段。 年龄也是一个可以用作搜索的字段。
  - 组合搜索,就是。 将 name 和 age 这两个字段, 甚至更多的字段进行一个组合的搜索。
  -  在这个基础上, 我们可以添加上, 模糊一点的条件, 比如 age>20。

先看一下我想做的,这张表把:

class UserInfo(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(verbose_name="用户名", max_length=32)
pwd = models.CharField(verbose_name="密码", max_length=16)
age = models.CharField(verbose_name="年龄", max_length=3) depart = models.ForeignKey(verbose_name="部门", to="Depart", to_field="id", on_delete=models.CASCADE) class_choice = [
(1, "九年级一班"),
(2, "九年级二班"),
(3, "九年级三班"),
]
classes = models.IntegerField(verbose_name="班级", choices=class_choice, default=1)
gender_choice = [
(1, "男"),
(2, "女")
]
gender = models.IntegerField(verbose_name="性别", choices=gender_choice, default=1) def __str__(self):
return self.name

分析得出的结果就是。 这里有7 个字段。 id 先不考虑。 pwd 密码也不考虑。

name 字段。 使用关键字的方式, 进行模糊的查询。
age 字段可以, 做一个区间,让用户来选择。

而 对于, choice 的这种字段。 应该把所有的选项,都罗列出来, 让用户自己选择。
gender 字段,应该做一个, 下拉框。 默认 全部选中。  如果用户选了 男 那么。 就过滤出 男性的人。 反之就是女
classes 字段, 也是一样的。

而对于, ForeignKey 或者 OneToOne   ManyToMany  这种的。 应该将被关联的这张表中, 所有的字段, 也做一个同样的展示。

开始搞:
  - 基类中配置, 一个 search_group = [] 
  - 和 一个函数  def get_search_group(self):    return self.search_group   预留钩子函数,让用户可以进行,权限的不同是否展示的功能

然后在 子类中。 开始进行。 具体的配置项:
  

class UserInfoHandler(StartHandler):
list_display = [StartHandler.display_checkbox, "name", "age", "depart", get_choice_txt("班级", "classes"),
get_choice_txt("性别", "gender"), StartHandler.display_edit, StartHandler.display_del]
per_page = 10
ordered_list = ["id"]
search_list = ["name__contains", "age__gt"]
action_list = [StartHandler.action_multi_delete, StartHandler.action_multi_init]
   has_add_btn = True # 配置组合搜索,想要展示哪些, 搜索的条件
search_group = ["gender", "classes", "depart"]

基类的处理:

search_group = []  # 方便,用户自己定制。组合搜索搜索的条件,和如果用户不配置,页面不显示组合搜索
def get_search_group(self):
return self.search_group per_page = 10 # 默认每页显示,多少数据。 也可在子类中,自行定制
def check_list_view(self, request, *args, **kwargs):
   ....... 其他代码在这里不贴了....... # ####################7. 处理组合搜索###################
from django.db.models import ForeignKey, ManyToManyField, OneToOneField
search_group = self.get_search_group() # ["gender", "classes", "depart"]
for item in search_group:
# 根据gender或者classes字符串,组自己对应的model类中,找到字段对象,再根据对象,获取关联的数据
field_obj = self.model_class._meta.get_field(item) # 固定用法mate 类,中的get_field() 就可以根据字符串获取对应的对象
# 对field_obj 的类型做判断。 来确定他是一个 choice 还是一个 foreignkey 外键
if isinstance(field_obj, ForeignKey) or isinstance(field_obj, ManyToManyField) or isinstance(field_obj,OneToOneField):
# 获取关联表中的, 数据 django1.0 版本使用 field_obj.rel.model.objects.all()
field_obj.related_model.objects.all() # django2.0版本使用这种方式 可以拿到, 被关联表的所有数据。
else:
# 获取 choice 的数据 field_obj.choices 使用这个对象下的 choices 方法,就能获取到,choices的元组.
print(field_obj.choices)
       # [(1, '男'), (2, '女')] [(1, '九年级一班'), (2, '九年级二班'), (3, '九年级三班')]
return render(request, "stark/changelist.html",
{"header_list": header_list, "data_list": data_list,
"body_list": body_list,
"pager": pager,
"add_btn": add_btn,
"search_list": search_list,
"search_value": search_value,
"action_dict": action_dict})
ok 做到这一部分,基本已经可以实现,组合搜索。 如何从数据库取出数据了! 但是如果可能更加的便捷,并且还可以支持动态的 搜索。 这样就不够了。
因为 子类中 search_group = ["gender", "classes", "depart"] 这里是写死了的, 而且没有任何的条件。 这里只是将所有的数据查询了出来。

并没有像, 比如我要查询 Depart 表中。 id 大于5 的这些数据。  如果要实现这种的,我们可能就需要一个字典。
例: {"field":"depart", "db_condition":{"id__gt":5}}  这种的数据结构。 通过 field字段,查询出对应的表。然后根据 条件dn_condition  来进行条件的,过滤。

这样的话,我在子类中的  search_group 列表, 可能就需要写很多的字典,进去。 而且还有一点,无法做到。根据前端发送过来的数据。进行 动态的筛选。  比如, 我不想要 大于5 了,  我想要 大于3 呢?

所以, 我这里使用了, 在 search_group 类表中,放置一个 对象进行去:

看一看 生成对象的类:

class Option(object):
'''使用组合搜索, 想要一些自己的搜索条件。 可扩展可继承'''
def __init__(self, field, db_condition=None):
'''
:param filed: 组合搜索关联的字段
:param db_condition: 数据库关联查询时查询的条件
'''
self.field = field
self.db_condition = db_condition
if not db_condition:
db_condition = {}
self.db_condition = db_condition def get_db_condition(self, request, *args, **kwargs):
'''预留继承后的重写函数, 重写后,次基类中的该方法,将被覆盖。 默认返回的是开发者输入的值。'''
'''重写后, 可根据,前端的返回值,进行一定的判断'''
return self.db_condition def get_queryset_or_tuple(self, model_class, request, *args, **kwargs):
'''根据字段去获取数据库关联的数据''' # 根据gender或者classes字符串,组自己对应的model类中,找到字段对象,再根据对象,获取关联的数据
field_obj = model_class._meta.get_field(self.field) # 固定用法mate 类,中的get_field() 就可以根据字符串获取对应的对象
# 对field_obj 的类型做判断。 来确定他是一个 choice 还是一个 foreignkey 外键
if isinstance(field_obj, ForeignKey) or isinstance(field_obj, ManyToManyField):
# 获取关联表中的, 数据 django1.0 版本使用 field_obj.rel.model.objects.all()
db_condition = self.get_db_condition(request, *args, **kwargs)
query_set = field_obj.related_model.objects.filter(**db_condition)
print(query_set)
else:
# 获取 choice 的数据 field_obj.choices
print(field_obj.choices)

ok  有个这个类的情况下:  我们在  handler 子类中。  search_group 列表:

    search_group = [
Option("gender"),
Option("classes"),
Option("depart"),
]

有了这个列表, 在视图函数中。 循环的时候, 拿到的就是。 这个对象。
直接调用,对象下的   get_queryset_or_tuple()  就可以了!   并且 这个函数中。
还有一个 获取条件的函数  self.get_db_condition(request, *args, **kwargs): 默认返回的就是一个 空字典。 代表没有任何的条件。

如果我想要加上条件, 也是很简单:

    search_group = [
Option("gender"),
Option("classes"),
Option("depart",{"id__gt":5}),
]

ok 没有问题。 最想要的动态查询呢?  也是很 easy   我只需要 再写一个 子类 并且继承  Option 类,然后重写 get_db_condition 就可以了

class MyOption(Option):
'''一个例子,这样重写之后。 Handler类中。 将使用这个方法,来生成对象。 从而覆盖掉基类的方法'''
'''并且可以根据,request。 传进来的数据,进行动态的查询。'''
def get_db_condition(self, request, *args, **kwargs):
return {"id__gt": request.GET.get("nid")}

相应的, serach_group  就需要, 使用这个子类。来构造对象: 并且也不需要在传入,条件参数

    search_group = [
Option("gender"),
Option("classes"),
MyOption("depart"),
]

这样,当对象去调用  get_db_condition  的时候。 会优先使用,自己类中的这个方法。

返回的就是  自己类中的这个方法,返回的 字典。  而且这个字典,是我们通过获取前端发送来的数据,从而进行生成  条件字典。
进而,获取相应的数据。
也就达到了,动态。 获取数据的目的。

stark组件开发之组合搜索实现思路的更多相关文章

  1. stark组件开发之组合搜索页面效果和 URL

    页面效果,只是样式.这个好解决!yield 的时候. 返回几个样式出去就好了! 并且前端写上一些样式的css {% if search_group_row_list %} <div class= ...

  2. stark组件开发之组合搜索高级显示和扩展

    上一篇,我只是做了. 默认的显示. def __iter__(self): '''默认显示. 用户可以自定制''' if isinstance(self.queryset_or_tuple, list ...

  3. stark组件开发之组合搜索基本显示

    数据的获取,上一篇,已经有了!然后就是,如何进行展示的问题.到了展示这里,又有了新的问题, 因为从数据库,取得的数据. 分为 queryset 和 tuple 两种数据结构.tuple 中,只是字符串 ...

  4. stark组件开发之关键搜索

    - 模糊搜索: 在页面生成一个表单.  以get 方式, 将数据提交到.当前查看页面. 后台接收数据,然后进行筛选过滤. 着个也需要,用户自定制!   定义一个  search_list  这个值,默 ...

  5. stark组件开发之列表页面定制列

    先看一张页面展示的效果图: 看一看我的  model 表!是什么样子: 看一看数据库是什么样子: 看 页面展示图,有表头. 有数据.模型表中,每一个字段, 都指定了 verbose_name. 如何解 ...

  6. stark组件开发之列表页面应用示例

    已经解决的,自定义的扩展函数,功能.但是 不可能返回. 一个 固定的页面把!  应该是,点击那条 记录之后的编辑, 就会跳转到相应的,编辑页面.所以 这个标签的  <a href="/ ...

  7. 轮播组件/瀑布流/组合搜索/KindEditor插件

    一.企业官网 ### 瀑布流 ​ Models.Student.objects.all() #获取所有学员信息 ​ 通过div进行循环图片和字幕 ​ 1.以template模板方法实现瀑布流以列为单位 ...

  8. stark组件开发之添加功能实现

    添加功能,还是使用, form 组件来完成!  并且 完成添加之后,需要保留原搜索条件. def memory_url(self): '''用于反向生成url, 并且携带,get请求的参数,跳转到下一 ...

  9. stark组件开发之编辑功能实现

    编辑功能.和添加一样! 唯一不同的就是, 需要编辑一个指定的  记录.这就需要,在列表页面, 渲染编辑的时候,添加一个 id 值: class UserInfoHandler(StartHandler ...

随机推荐

  1. CTO 技能图谱

    岗位职责 建立技术团队文化 规划技术发展路线 落地产品研发成果 宣传公司技术品牌 吸引优秀技术人才 基本素质 正直诚实的道德修养 谦虚谨慎的工作态度 随机应变的处事风格 统领全局的战略思维 硬技能 技 ...

  2. flutter 访问网页+http请求

    一.目录 1.访问网页 2.http请求 -----------------------------这是分割线----------------------------- 1.访问网页 基于url_la ...

  3. 基础总结(01)--css清除浮动几种方法

    1.父元素添加overflow:auto/hidden; 2.父元素内加空div,添加样式clear:both; 3.父元素添加伪类; .parent:after{ content:''; displ ...

  4. java使用jxl,poi解析excel文件

    public interface JavaExcel { /** * 使用jxl写excel文件 */ public void writeJxlExcel(); /** * 使用jxl读excel文件 ...

  5. thunderbird 日历

    参考: Configuring Thunderbird and Using it to Access Office 365 Mail and Calendar in Cardiff Universit ...

  6. 【学习】数据规整化:清理、转换、合并、重塑(续)【pandas】

    @合并重叠数据 还有一种数据组合问题不能用简单的合并或连接运算来处理.比如说,你可能有索引全部或部分重叠的两个数据集 使用numpy的where函数,它用于表达一种矢量化的if - else a = ...

  7. 【C语言基础】变量

    1.什么是变量? 变量的本质就是内存中一段储存空间 2.变量为什么必须初始化? 所谓初始化就是赋值的意思 3.如何定义变量 数据类型 变量名 = 要赋的值 举例子: int i = 3:等价于 int ...

  8. ThreeJs 模型的缩放、移动、旋转 以及使用鼠标对三维物体的缩放

    首先我们创建一个模型对象 var geometry = new THREE.BoxGeometry( 100, 100, 100); //边长100的正方体 var material = new TH ...

  9. rad 10.2

    最大分辨率跟笔记本走了 笔记本最大分辨率 1388 程序界面是 1980*1080 笔记本打开过程序,就自动变为  1388了,界面全乱了.因为设置的 锚点是 右下.

  10. take it easy

    昨天魏辉在群里说,觉得自己以前很多事情做的不对,以前是个傻瓜,我说我也是这么觉得的.为什么这么说呢?因为我真的觉得以前的自己就是个SB.人的成长可能就是这样的吧,小时候的一些事情,或者是原生家庭的环境 ...