当前位置: 首页 > news >正文

Django项目之订单管理part6(message组件和组合搜索组件)

一.前言

我们前面讲的差不多了,接着上节课讲,今天要来做一个撤单要求,我们可以用ajax请求,但是我这里介绍最后一个知识点,message组件,但是我会把两种方式都讲出来的,讲完这个就开始讲我们最重要的worker

二.message组件

2.1 message基础配置

打开app 

打开中间件

打开模板

第四个位置,自定义

# MESSAGE_STORAGE = 'django.contrib.messages.storage.fallback.FallbackStorage'
# MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' 

2.2 设置值

from django.contrib import messages
messages.add_message(reqeust, messages.SUCCESS, "删除成功1")
messages.add_message(reqeust, messages.ERROR, "操作失败") 

 2.3 读取值

py中读取 

from django.contrib.messages.api import get_messages
messages = get_messages(request)
for msg in messages:
    print(msg)

html中读取

<ul>
    {% for message in messages %}
        <li>{{ message.tags }} {{ message }}</li>
    {% endfor %}
</ul>

读取值以后就默认删除了,有点像队列  

三.客户撤单

3.1 撤单的页面展示

我们借助bootstrap,成功是成功的弹出框,失败是失败的弹出框,这时候就要用到里面的level_tag,正好和bootstarap对应上了

末尾再加个定时器,这样就刚好展示三秒

这里加上设置的这个配置是因为这个里面默认没有danger,但是bootstrap里面是有danger的,所以我们得自定义属性,让他能够展示danger的错误页面,所以我们这样设置,因为没和大家说源码,所以大家肯定是不太懂得,但是记住就好。

 3.2 撤单逻辑处理

这个和前面做的都一样,也没啥区别

四.我的交易记录 

我们前面做了一个我的交易记录,这里我们还要做一个客户得交易记录,这里还是实现一个新的功能,就是组合搜索。

这里我直接用写好的组件,当然这个是机构的组件,我这里讲一下用法

4.1 组合搜索组件得用法

组件源码

#!/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 SearchGroup(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

  # 第一步:配置和传参
    search_group = NbSearchGroup(
        request,
        models.TransactionRecord,
        Option('charge_type'),  # choice 或者forikey字段

        #也可也加上 Option('level',db_condition={'active':1})搜索条件

        #  is_multi=True 允许多选


    )

    # 第二步:获取条件 .filter(**search_group.get_condition)
    queryset = models.TransactionRecord.objects.filter(**search_group.get_condition)
    pager = Pagination(request, queryset)

    context = {
        "pager": pager,
        "keyword": keyword,
        "search_group": search_group  # 第三步:传入前端页面
    }

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

母版

<link rel="stylesheet" href="{% static 'css/search-group.css' %}"> 

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

html

{% block content %}
    {% include 'include/search_group.html' %}
{% endblock %} 

4.2 交易记录逻辑 

 

这样就ok了

五.所有交易记录

这个代码和前面基本一样,也没啥知识点了,所以我就直接放在这里了

这样就ok了

六.总结

我们这样就把所有的展示功能以及数据库的全部功能实现了,现在就只差worker和上传服务器,这里下一节再讲,把这里全部都和大家梳理一下。

  • 权限和菜单

    • 动态菜单,不同用户角色【配置文件】

      - 配置文件,写配置用户级别配置 + 默认配置
      - 构造属于自己的结构:权限、菜单字典。
      - 数据库获取用户角色
    • 默认选中和展开

      - inclusion_tag
    • 权限校验

      - 中间件
      - request.nb_user 赋值
    • 控制按钮是否显示

      - filter,可以模板语言中的if else的条件
  • 基于Form和ModelForm实现增删改查

  • 构建的了BootStrapForm类实现BootStrap样式 + 免除BootStrap样式

  • 删除/撤单

    • 直接超链接删除,跳转

    • 对话框 + ajax删除(推荐)

    • 直接超链接删除,跳转 + message => 成功和失败的提醒。(推荐)

  • 添加和编辑

    • 跳转到添加和编辑页面,成功后跳转回来。

    • 对话框 + ajax

  • 原条件保留

    • 删除

    • 编辑

  • 分页

  • 关键字搜索

  • 组合搜索

七.补充 

下一期将和大家开始讲的内容有点多,希望大家的关注加收藏,不懂得看我的名字和签名,一起交流学习

相关文章:

  • 繁华 李劭卓2025.3.28
  • RWEQ 模型深度讲解:结合 Python、ArcGIS 等实现土壤风蚀归因分析
  • 【CVE-2025-30208】| Vite-漏洞分析与复现
  • DQN与PPO在算法层面的核心区别
  • Binance Wallet
  • 2024年SEVC SCI1区:进化尺度适应差分进化算法ESADE,深度解析+性能实测
  • 运维面试题(十一)
  • 可以通过哪种方式实现安卓应用生成下载链接
  • 音视频 四 看书的笔记 MediaPlayerService
  • 《非暴力沟通》第四章 “体会和表达感受” 总结
  • 快速了解ES6Module模块化
  • CLion的坑:CMake File API : no reply dir found clion
  • 【强化学习】DAPO 论文解读
  • 什么是索引下推和索引覆盖?
  • 06-SpringBoot3入门-常见注解(简介)
  • 《破局摩尔定律:AI驱动、异构集成与工具革新重构芯片效能新范式》
  • Redis数据迁移同步
  • 乳腺超声图像结节分割
  • LeetCode算法题(Go语言实现)_15
  • 煤矿油田光伏管理新突破:安科瑞分布式监控系统如何破解高耗能行业转型难题
  • 美国新泽西客运公司遭遇罢工:40年来首次,35万人受影响
  • ESG考证虚火:相比证书,知识结构+实战经验更重要
  • 中国—美国经贸合作对接交流会在华盛顿成功举行
  • 证券日报:降准今日正式落地,年内或还有降准空间
  • 冰雹造成车损能赔吗?如何理赔?机构答疑
  • 国家林业和草原局原党组成员、副局长李春良接受审查调查