django常用的组合搜索组件

news2025/3/1 15:56:18

文章目录

  • django常用的组合搜索组件
    • 快速使用
      • 配置信息
      • 1. 视图函数
      • 2. 前端模板
      • 3. css样式
    • 代码实现

django常用的组合搜索组件

在项目开发中,如果有大量数据就要用到组合搜索,通过组合搜索对大块内容进行分类筛选。

在这里插入图片描述

快速使用

三步走:(其实主要就是传入配置信息)

  1. 创建组合搜索类的实例对象,传入参数进行配置(三个参数: request, model_class, *options
  2. 在数据库查询时传入search_group.get_condition方法生成的查询条件(该方法会根据传入的配置生成查询条件)
  3. 在前端使用search_group.get_row_list(search_group.get_row_list生成一个列表,包含所有传入的Option字段的信息)

配置信息

这是Option类的init函数:

class Option(object):
    def __init__(self, field, is_condition=True, is_multi=False, db_condition=None, text_func=None, value_func=None):
        """
        :param field: 组合搜索关联的字段(支持choice/Foreignkey类型)
        :param is_multi: 是否支持多选
        :param db_condition: 数据库关联查询时的条件(字典)
        :param text_func: 此函数用于显示组合搜索按钮页面文本(页面展示的值)
        :param value_func: 此函数用于显示组合搜索按钮值(url中的参数值)
        """
        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

示例:

search_group = NbSearchGroup(
        request,
        models.TransactionRecord,
        Option('charge_type', 
               is_multi=True, 
               text_func=lambda x: x[1],
               value_func=lambda x:x[0]
              ),  # choice
        Option('customer', 
               db_condition={"id__lte": 10, 'active': 1}, 
               text_func=lambda x: x.username,value_func=lambda x:x.id
              ),  # fk
    )

在这里插入图片描述

1. 视图函数

from django.shortcuts import render
from web import models
from utils.pager import Pagination
from django.db.models import Q
from utils.group import Option, NbSearchGroup

def my_transaction_list(request):
    # 第一步:配置和传参
    search_group = NbSearchGroup(
        request,
        models.TransactionRecord,
        Option('charge_type'),  # choice
    )
    
    # ...其他的查询条件

    # 第二步:获取条件 .filter(**search_group.get_condition)
    queryset = models.TransactionRecord.objects.filter(**search_group.get_condition).filter(其他查询条件)
    pager = Pagination(request, queryset) # 分页组件

    context = {
        "pager": pager,
        "keyword": keyword,
        "search_group": search_group  # 第三步:将对象传入前端页面
    }
    return render(request, 'my_transaction_list.html', context)

2. 前端模板

{% 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 %}

3. 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;
}

代码实现

#!/usr/bin/env python
# -*- coding:utf-8 -*-
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):
        """
        :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

若有错误与不足请指出,关注DPT一起进步吧!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2040084.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

刷题记录第110天-分割等和数组

解题思路&#xff1a; 问题可转化为&#xff0c;用给定数组能否装满一个容量为数组总和一半的背包(targetsum/2)&#xff0c;即一个0-1背包问题。 0-1背包问题的关键在于数组的定义和状态转移方程以及价值的定义。dp[i][j]表示在[0…i]个物品内&#xff0c;背包容量为j能装的最…

再升级!MoneyPrinterPlus集成GPT_SoVITS

最近有很多优秀的语音合成TTS工具&#xff0c;目前MoneyPrinterPlus已经集成了ChatTTS和fasterWhisper。应朋友们的要求&#xff0c;最近MoneyPrinterPlus也集成了GPT_SoVITS这个优秀的语音合成工具。 今天给大家详细讲解一下&#xff0c;如何在MoneyPrinterPlus中使用GPT_SoV…

机器学习速成第三集——无监督学习之降维(理论部分)!

目录 主成分分析&#xff08;PCA&#xff09; 独立成分分析&#xff08;ICA&#xff09; t分布随机邻近嵌入&#xff08;t-SNE&#xff09; 线性判别分析&#xff08;LDA&#xff09; 其他降维方法 应用场景 主成分分析&#xff08;PCA&#xff09;在处理大规模数据集时…

新能源汽车电机低频电磁场仿真应用

一、背景介绍 随着新能源汽车的普及&#xff0c;电机作为新能源汽车驱动系统的核心组成部分&#xff0c;其重要性不言而喻。电机使电能转化为机械能&#xff0c;通过传动系统将机械能传递到车轮&#xff0c;驱动汽车行驶。新能源汽车电机的发展经历了从初步探索到技术成熟的多…

Localization Translate API 的对接和使用

Localization Translate API 的对接和使用 Localization Translate API 的主要功能是通过输入需要翻译的文本来获取翻译后的文本&#xff0c;同时翻译后的语言可以自定义&#xff0c;并且翻译结果可以采用 json &#xff0c; markdown 俩种主流的方法来输出。 本文档将详细介…

【安卓】多线程编程

文章目录 线程的简单应用解析异步消息处理机制使用AsyncTask 线程的简单应用 新建一个AndroidThreadTest项目&#xff0c;然后修改activity_main.xml中的代码。 <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width…

CNN-GRU神经网络多输入单输出回归预测【MATLAB】

1. CNN&#xff08;卷积神经网络&#xff09;部分 作用&#xff1a; 特征提取&#xff1a;CNN擅长从输入数据中提取空间特征。在多输入情况下&#xff0c;它可以处理来自不同源的数据&#xff0c;提取有用的特征。 局部感受野&#xff1a;通过卷积操作&#xff0c;CNN能够识别…

【ACM出版,往届会后三个半月EI见刊/检索】第四届物联网与机器学习国际学术会议(IoTML 2024,8月23-25)

2024年第四届物联网与机器学习国际学术会议&#xff08;IoTML 2024&#xff09;将于2024年8月23-25日在中国南昌召开。 会议将围绕着物联网和机器学习开展&#xff0c;探讨本领域发展所面临的关键性挑战问题和研究方向&#xff0c;以期推动该领域理论、技术在高校和企业的发展和…

vector嵌套之空指针异常

文章目录 1. 题目链接2. 题目代码正确代码错误代码 1. 题目链接 118. 杨辉三角 2. 题目代码 正确代码 class Solution { public:vector<vector<int>> generate(int numRows) {vector<vector<int>> result(numRows);for(int i 0; i < numRows; i)…

STL中的栈(stack)和队列(queue)以及简单(复用)实现

适配器&#xff1a; 虽然 stack 和 queue 中也可以存放元素&#xff0c;但在 STL 中并没有将其划分在容器的行列&#xff0c;而是将其称为 容器适配器 &#xff0c;这是因为 stack 和队列只是对其他容器的接口进行了包装&#xff0c; STL 中 stack 和 queue 默认使用deque 换种…

【云备份】学习Json

文章目录 1.Json数据类型基础数据类型复合数据类型JSON数据类型的应用 2.学习jsoncpp库利用json实现序列化利用json实现反序列化 1.Json数据类型 json 是一种数据交换格式&#xff0c;采用完全独立于编程语言的文本格式来存储和表示数据。json数据交换格式是将多种数据对象组织…

CVE-2024-38077 Windows远程桌面授权服务漏洞介绍

CVE-2024-38077 是一个在Windows远程桌面授权服务&#xff08;Remote Desktop Licensing Service&#xff09;中存在的严重远程代码执行漏洞。以下是关于此漏洞的详细信息&#xff1a; 漏洞概述 漏洞编号&#xff1a;CVE-2024-38077漏洞类型&#xff1a;远程代码执行 (RCE)影…

基于单片机控制的多功能智能语音风扇

【摘要】 本文简述了一种基于单片机控制的智能多功能语音风扇的设计&#xff0c;该设计以STC11L08XE单片机为主控制器&#xff0c;通过YS-LDV7语音模块对语音信号进行采集识别&#xff0c;并将该信号上传给单片机进而控制风扇的转速和开关&#xff0c;以达到语音控制的效果。该…

Python 安装 PyTorch详细教程

本章教程,介绍如何安装PyTorch,介绍两种安装方式,一种是通过pip直接安装,一种是通过conda方式安装。 一、查看CUDA版本 二、安装PyTorch 1、pip安装方式 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu1162、conda安装方式 …

Leetcode—3151. 特殊数组 I【简单】

2024每日刷题&#xff08;155&#xff09; Leetcode—3151. 特殊数组 I 实现代码 class Solution { public:bool isArraySpecial(vector<int>& nums) {int n nums.size();for(int i 1; i < n; i) {if(nums[i - 1] % 2 nums[i] % 2) {return false;}}return t…

【数据结构-前缀哈希】力扣1124. 表现良好的最长时间段

给你一份工作时间表 hours&#xff0c;上面记录着某一位员工每天的工作小时数。 我们认为当员工一天中的工作小时数大于 8 小时的时候&#xff0c;那么这一天就是「劳累的一天」。 所谓「表现良好的时间段」&#xff0c;意味在这段时间内&#xff0c;「劳累的天数」是严格 大…

练习实践-基础设施-文件共享-linux间的文件共享-NFS服务搭建

参考来源&#xff1a; nfs安装配置-Debian/Ubuntu 什么是NFS&#xff1f;NFS挂载 NFS详解&#xff08;概念实验演示&#xff09; 快速回顾&#xff1a; nfs服务器搭建&#xff1a;1>.服务器端&#xff1a;1&#xff09;创建共享目录2&#xff09;修改配置文件/etc/exports…

深入解析三路快排:一种高效的排序算法

在数据结构和算法的世界中&#xff0c;快排&#xff08;Quick Sort&#xff09;无疑是最受欢迎的排序算法之一。今天&#xff0c;探讨一种优化的快排变体——三路快排&#xff08;3-Way Quick Sort&#xff09;&#xff0c;它在处理具有重复元素的数组时展现出了令人惊叹的效率…

PCIe学习笔记(22)

Transaction Ordering Transaction Ordering Rules 表2-40定义了PCI Express Transactions的排序要求。该表中定义的规则统一适用于PCI Express上所有类型的事务&#xff0c;包括内存、I/O、配置和消息。该表中定义的排序规则适用于单个流量类(TC)。不同TC标签的事务之间没有…

Label-Wise Graph Convolutional Network for Heterophilic Graphs

推荐指数: #paper/⭐⭐ 发表于:LoG 2022 推荐指数是因为22年,所以给2行. 贡献:用MLP来区分不同的标签信息. 思想阐述: 假设 N k ( v ) \mathcal{N}_{k}(v) Nk​(v)表示节点v标签为k的邻居.我们定义基于 a v , k a_{v,k} av,k​为聚合标签为k的邻居:(即只聚合标签为k的邻居) a…