您现在的位置是: 网站首页 >Django >DjangoCRM客户关系管理 Django

【CRM客户关系管理】09.根据模型中字段的choices以及时间区间来过滤数据

admin2018年11月25日 19:55 Django | Html | Python 1312人已围观

DjangoCRM客户关系管理简介 使用Django2.1.3+Bootstrap实现CRM系统,仿照Django Admin重写后台 Github地址:https://github.com/xyliurui/DjangoCRM Django版本:2.1.3

### 添加过滤功能 先看使用方法,如何获得选项的值 ```python from crm import models x = models.CustomerInfo._meta.get_field('status') x <django.db.models.fields.SmallIntegerField: status> x.choices ((1, '未报名'), (2, '已报名'), (3, '结业')) x.get_choices() [('', '---------'), (1, '未报名'), (2, '已报名'), (3, '结业')] ``` #### 添加过滤的模板标签 ```python @register.simple_tag def build_option_filter(filter_field, admin_class): select = "<select name='{}'>".format(filter_field) # 获取列中的字段对象 filter_field_obj = admin_class.model._meta.get_field(filter_field) for choice in filter_field_obj.get_choices(): option = "<option value='{}'>{}</option>".format(choice[0], choice[1]) select += option select += "</select>" return mark_safe(select) ``` #### table_detail.html页面增加过滤表单 ```html {% extends 'djadmin/base.html' %} {% load djadmin_tags %} {% block title %} 数据表详情 - 后台管理 {% endblock %} {% block content %} <h1 class="page-header">应用 - {{ app_name }}</h1> {{ queryset }} <p> <form> {% for filter_field in admin_class.list_filter %} {% build_option_filter filter_field admin_class %} {% endfor %} <button type="submit">过滤</button> </form> </p> <table class="table table-striped"> <thead> <tr> <!-- {% for display_field in admin_class.list_display %} <th>{{ display_field }}</th> {% endfor %} --> {% build_table_head_name admin_class %} </tr> </thead> <tbody> {% for obj in queryset %} <tr> {% build_table_body obj admin_class %} </tr> {% endfor %} </tbody> </table> {% endblock %} ``` 刷新 http://127.0.0.1:8000/djadmin/crm/customerinfo/ 页面,会出现错误 ``` AttributeError at /djadmin/crm/customerinfo/ 'NoneType' object has no attribute 'model' ``` 这是因为时间的过滤方式不对,在crm应用的`CustomerInfoAdmin(BaseDjAdmin)`类中去掉过去时间,就会正常显示了 ![BLOG_20181126_111022_24](/media/blog/images/2018/11/BLOG_20181126_111022_24.png "博客图集BLOG_20181126_111022_24.png") 但是不能这样做,接下来就来获取这个异常,然后用另外的方式处理时间过滤 #### 处理过滤模板标签中的时间字段选项 继续修改`build_option_filter(filter_field, admin_class)`函数 ```python @register.simple_tag def build_option_filter(filter_field, admin_class): select = "<select name='{}'>".format(filter_field) # 获取列中的字段对象 filter_field_obj = admin_class.model._meta.get_field(filter_field) try: for choice in filter_field_obj.get_choices(): option = "<option value='{}'>{}</option>".format(choice[0], choice[1]) select += option except AttributeError as e: # print(filter_field_obj.get_internal_type()) # 这儿得到的结果是:DateField if filter_field_obj.get_internal_type() in ('DateField', 'DateTimeField'): import datetime now_time = datetime.datetime.now() filter_time_list = [ ('', '所有时间'), (now_time, '今天'), (now_time - datetime.timedelta(7), '7天内'), # 往前7天 (now_time.replace(day=1), '本月'), # 本月内 (now_time - datetime.timedelta(90), '三个月内'), (now_time.replace(month=1, day=1), '本年'), ] for dt in filter_time_list: option = "<option value='{}'>{}</option>".format(dt[0], dt[1]) select += option select += "</select>" return mark_safe(select) ``` #### 视图中处理过滤结果 首先定义一个过滤函数,与获取request的值,然后对传入的查询集进行过滤,最后返回,视图中只需要调用这个过滤函数 ```python def get_filter_result(request, queryset): """获取过滤的字段,并返回过滤后的查询集和过滤的字典""" filter_conditions = {} # 获取过滤的字段 for k, v in request.GET.items(): if v: # 所选的值不会空是保存到字典中 filter_conditions[k] = v return queryset.filter(**filter_conditions), filter_conditions @login_required def table_detail(request, app_name, model_name): """取出指定model里的数据返回到前端""" # 拿到admin_class后,通过它获取model admin_class = site.enable_admins[app_name][model_name] # print(admin_class) # 执行djadmin.py定义的注册模型类 queryset = admin_class.model.objects.all() # print(queryset) # 进行过滤 queryset, filter_conditions = get_filter_result(request, queryset) # 将过滤字典保存到全局注册类中 admin_class.filter_conditions = filter_conditions return render(request, 'djadmin/table_detail.html', locals()) ``` #### 处理模板标签中过滤选中 当选择过滤条件后,给对应值添加选中状态 `selected=selected` ```python @register.simple_tag def build_option_filter(filter_field, admin_class): select = "<select name='{}'>".format(filter_field) # 获取列中的字段对象 filter_field_obj = admin_class.model._meta.get_field(filter_field) try: for choice in filter_field_obj.get_choices(): # choice[0]为选项的值,choice[1]为选中的可见内容 # 获取过滤字典中的值,并在模板中呈选中状态 selected = '' if filter_field in admin_class.filter_conditions: # 如果当前值被选中 if str(choice[0]) == admin_class.filter_conditions.get(filter_field): selected = 'selected' option = "<option value='{}' {}>{}</option>".format(choice[0], selected, choice[1]) select += option except AttributeError as e: # print(filter_field_obj.get_internal_type()) # 这儿得到的结果是:DateField if filter_field_obj.get_internal_type() in ('DateField', 'DateTimeField'): import datetime now_time = datetime.datetime.now() filter_time_list = [ ('', '所有时间'), (now_time, '今天'), (now_time - datetime.timedelta(7), '7天内'), # 往前7天 (now_time.replace(day=1), '本月'), # 本月内 (now_time - datetime.timedelta(90), '三个月内'), (now_time.replace(month=1, day=1), '本年'), ] for dt in filter_time_list: option = "<option value='{}'>{}</option>".format(dt[0], dt[1]) select += option select += "</select>" return mark_safe(select) ``` ![BLOG_20181126_111038_40](/media/blog/images/2018/11/BLOG_20181126_111038_40.png "博客图集BLOG_20181126_111038_40.png") 这时链接变成了 http://127.0.0.1:8000/djadmin/crm/customerinfo/?source=2&consultant=&status=1&created_time= #### 处理过滤时间报错问题 在过滤时间时会报错 ``` ValidationError at /djadmin/crm/customerinfo/ ['’2018-11-10 16:53:18.818027‘ 必须为合法的日期格式,请使用 YYYY-MM-DD 格式。'] ``` 继续修改`build_option_filter(filter_field, admin_class)`模板标签,将时间进行格式化,并增加选中功能 ```python @register.simple_tag def build_option_filter(filter_field, admin_class): select = "<select name='{}'>".format(filter_field) # 获取列中的字段对象 filter_field_obj = admin_class.model._meta.get_field(filter_field) try: for choice in filter_field_obj.get_choices(): # choice[0]为选项的值,choice[1]为选中的可见内容 # 获取过滤字典中的值,并在模板中呈选中状态 selected = '' if filter_field in admin_class.filter_conditions: # 如果当前值被选中 if str(choice[0]) == admin_class.filter_conditions.get(filter_field): selected = 'selected' option = "<option value='{}' {}>{}</option>".format(choice[0], selected, choice[1]) select += option except AttributeError as e: # print(filter_field_obj.get_internal_type()) # 这儿得到的结果是:DateField if filter_field_obj.get_internal_type() in ('DateField', 'DateTimeField'): import datetime now_time = datetime.datetime.now() filter_time_list = [ ('', '所有时间'), (now_time, '今天'), (now_time - datetime.timedelta(7), '7天内'), # 往前7天 (now_time.replace(day=1), '本月'), # 本月内 (now_time - datetime.timedelta(90), '三个月内'), (now_time.replace(month=1, day=1), '本年'), ] for dt in filter_time_list: # 如果选择的时间值不为空,则进行时间格式化 time_to_str = '' if not dt[0] else dt[0].strftime('%Y-%m-%d') # 需要将时间格式化成:YYYY-MM-DD # 设置选中 selected = '' if filter_field in admin_class.filter_conditions: # 如果当前值被选中 if time_to_str == admin_class.filter_conditions.get(filter_field): selected = 'selected' option = "<option value='{}' {}>{}</option>".format(time_to_str, selected, dt[1]) select += option select += "</select>" return mark_safe(select) ``` ![BLOG_20181126_111106_36](/media/blog/images/2018/11/BLOG_20181126_111106_36.png "博客图集BLOG_20181126_111106_36.png") 现在不会报错了,但是除了今天的日期过滤,其他区间日期都不能正常过滤 ![BLOG_20181126_111115_83](/media/blog/images/2018/11/BLOG_20181126_111115_83.png "博客图集BLOG_20181126_111115_83.png") #### 处理过滤时间数据为空的问题 因为其它条件过滤的时候值是等于,但是根据时间过滤应该是大于等于才对 继续修改`build_option_filter(filter_field, admin_class)`函数,将处理时间的选项`name`改为`{}__gte`大于等于`select = "<select name='{}__gte'>".format(filter_field)`,同时修改选中的判断 ```python @register.simple_tag def build_option_filter(filter_field, admin_class): select = "<select name='{}'>".format(filter_field) # 获取列中的字段对象 filter_field_obj = admin_class.model._meta.get_field(filter_field) try: for choice in filter_field_obj.get_choices(): # choice[0]为选项的值,choice[1]为选中的可见内容 # 获取过滤字典中的值,并在模板中呈选中状态 selected = '' if filter_field in admin_class.filter_conditions: # 如果当前值被选中 if str(choice[0]) == admin_class.filter_conditions.get(filter_field): selected = 'selected' option = "<option value='{}' {}>{}</option>".format(choice[0], selected, choice[1]) select += option except AttributeError as e: # 对时间使用单独的select select = "<select name='{}__gte'>".format(filter_field) # print(filter_field_obj.get_internal_type()) # 这儿得到的结果是:DateField if filter_field_obj.get_internal_type() in ('DateField', 'DateTimeField'): import datetime now_time = datetime.datetime.now() filter_time_list = [ ('', '所有时间'), (now_time, '今天'), (now_time - datetime.timedelta(7), '7天内'), # 往前7天 (now_time.replace(day=1), '本月'), # 本月内 (now_time - datetime.timedelta(90), '三个月内'), (now_time.replace(month=1, day=1), '本年'), ] for dt in filter_time_list: # 如果选择的时间值不为空,则进行时间格式化 time_to_str = '' if not dt[0] else dt[0].strftime('%Y-%m-%d') # 需要将时间格式化成:YYYY-MM-DD # 修改name后,过滤时间的参数变成了created_time__gte=2018-11-03,所以下方的选中,需要进行修改 # 设置选中 selected = '' if filter_field + '__gte' in admin_class.filter_conditions: # 如果当前值被选中 if time_to_str == admin_class.filter_conditions.get(filter_field + '__gte'): selected = 'selected' option = "<option value='{}' {}>{}</option>".format(time_to_str, selected, dt[1]) select += option select += "</select>" return mark_safe(select) ``` ![BLOG_20181126_111145_33](/media/blog/images/2018/11/BLOG_20181126_111145_33.png "博客图集BLOG_20181126_111145_33.png") #### 修改过滤选项和按钮的样式 修改table_detail.html增加`form`的样式 ```html <p> <form class="navbar-form navbar-left"> {% for filter_field in admin_class.list_filter %} {% build_option_filter filter_field admin_class %} {% endfor %} <button type="submit" class="btn btn-primary">过滤</button> </form> </p> ``` 然后修改`build_option_filter(filter_field, admin_class)`模板标签中`select`样式,两处修改 ```python # ...... select = "<select name='{}' class='form-control'>".format(filter_field) # ...... select = "<select class='form-control' name='{}__gte'>".format(filter_field) # ...... ``` 最终显示如下 ![BLOG_20181126_111158_49](/media/blog/images/2018/11/BLOG_20181126_111158_49.png "博客图集BLOG_20181126_111158_49.png")

很赞哦! (0)

文章交流

  • emoji
0人参与,0条评论

当前用户

未登录,点击   登录

站点信息

  • 建站时间:网站已运行2300天
  • 系统信息:Linux
  • 后台程序:Python: 3.8.10
  • 网站框架:Django: 3.2.6
  • 文章统计:257 篇
  • 文章评论:63 条
  • 腾讯分析网站概况-腾讯分析
  • 百度统计网站概况-百度统计
  • 公众号:微信扫描二维码,关注我们
  • QQ群:QQ加群,下载网站的学习源码
返回
顶部
标题 换行 登录
网站