美文网首页
基于curd的复合条件查询

基于curd的复合条件查询

作者: 马小跳_ | 来源:发表于2017-12-20 22:23 被阅读11次
    • 自定义config类中配置作为要做组合条件的字段
    comb_filter = [
            v1.FilterOption('gender',is_choice=True),
            v1.FilterOption('depart'),
            v1.FilterOption('roles',multi=True)
        ]
    
    • CurdConfig类中配置
    comb_filter = []
        def get_comb_filter(self):
            res = []
            if self.comb_filter:
                res.extend(self.comb_filter)
            return res
    
    • ChangeList类中
    self.comb_filter = config.get_comb_filter()
    
    def gen_comb_filter(self):
        """
        生成器函数
        根据字段,获取与之关联的数据,交给FilterRow做处理
        :return:
        """
    
        """
        self.comb_filter = [
             FilterRow(((1,'男'),(2,'女'),)),
             FilterRow([obj,obj,obj,obj ]),
             FilterRow([obj,obj,obj,obj ]),
        ]
        """
        data_list = []
        for option in self.comb_filter:
            _field = self.model_class._meta.get_field(option.field_name)
            from django.db.models import ForeignKey,ManyToManyField
            if isinstance(_field,ForeignKey):
                row = FilterRow(option,option.get_querySet(_field),self.request)
            elif isinstance(_field,ManyToManyField):
                row = FilterRow(option,option.get_querySet(_field),self.request)
            else:
                row = FilterRow(option,option.get_choices(_field),self.request)
            data_list.append(row)
        return data_list
    
    • FilterOption类,用来配置作为搜索条件的字段
    class FilterOption(object):
        def __init__(self,field_name,multi=False,condition=None,is_choice=False):
            """
    
            :param field_name:字段名
            :param multi:是否多选
            :param condition:显示数据的筛选条件
            :param is_choice:字段是否是choice类型(否则为外键或多对多)
            """
            self.field_name = field_name
            self.multi = multi
            self.condition = condition
            self.is_choice = is_choice
    
        def get_querySet(self,_field):
            if self.condition:
                querySet = _field.rel.to.objects.filter(**self.condition)
            else:
                querySet = _field.rel.to.objects.all()
            return querySet
    
    
        def get_choices(self,_field):
            return _field.choices
    
    • FilterRow类,它的迭代对象为页面上显示的一行条件
    class FilterRow(object):
        def __init__(self, option, data, request):
            self.option = option
            self.data = data
            self.request = request  # request
    
        def __iter__(self):
            params = copy.deepcopy(self.request.GET)
            params._mutable = True
            current_id = params.get(self.option.field_name)  # 3
            current_id_list = params.getlist(self.option.field_name)  # [1,2,3]
    
            if self.option.field_name in params:  # 如果传来的参数中有这个字段,代表全选没有被勾中
                # del params[self.option.field_name]
                print(params)
                origin_list = params.pop(self.option.field_name)  # 删除对应字段,并记录下它的值
                print(params,origin_list)
                url = "{0}?{1}".format(self.request.path_info, params.urlencode())
                yield mark_safe('<a href="{0}" class="">全部</a>'.format(url))
                params.setlist(self.option.field_name, origin_list)  # 回复原状
            else:  # 传来的参数中没有这个字段,代表全选被勾中
                url = "{0}?{1}".format(self.request.path_info, params.urlencode())
                yield mark_safe('<a class="active" href="{0}">全部</a>'.format(url))
    
            for val in self.data:
                if self.option.is_choice:  # 字段是choice类型
                    pk, text = str(val[0]), val[1]
                else:  # 字段是外键或多对多类型
                    pk, text = str(val.pk), str(val)
    
                # 当前URL?option.field_name
                # 当前URL?gender=pk
                # self.request.path_info # http://127.0.0.1:8005/arya/crm/customer/?gender=1&id=2
                # self.request.GET['gender'] = 1 # &id=2gender=1
    
                if not self.option.multi:  # 单选
                    params[self.option.field_name] = pk
                    url = "{0}?{1}".format(self.request.path_info, params.urlencode())
                    if current_id == pk:
                        yield mark_safe("<a class='active' href='{0}'>{1}</a>".format(url, text))
                    else:
                        yield mark_safe("<a href='{0}'>{1}</a>".format(url, text))
                else:  # 多选 current_id_list = ["1","2"]
                    _params = copy.deepcopy(params)
                    id_list = _params.getlist(self.option.field_name)
    
                    if pk in current_id_list:
                        id_list.remove(pk)
                        _params.setlist(self.option.field_name, id_list)
                        url = "{0}?{1}".format(self.request.path_info, _params.urlencode())
                        yield mark_safe("<a class='active' href='{0}'>{1}</a>".format(url, text))
                    else:
                        id_list.append(pk)
                        # params中被重新赋值
                        _params.setlist(self.option.field_name, id_list)
                        # 创建URL
                        url = "{0}?{1}".format(self.request.path_info, _params.urlencode())
                        yield mark_safe("<a href='{0}'>{1}</a>".format(url, text))
    
    
    • changelist_view
    def changelist_view(self,request):
        """
        列表页面对应视图函数
        """
        # 处理action
        if request.method == 'POST' and self.get_show_action_list():
            func_name_str = request.POST.get('list_action')
            action_func = getattr(self, func_name_str)
            ret = action_func(request)
            if ret:
                return ret
    
        # 组合条件
        comb_condition = {}
        option_list = self.get_comb_filter()
        for key in request.GET.keys():
            value_list = request.GET.getlist(key)
            flag = False
            for option in option_list:
                if option.field_name == key:
                    flag = True
                    break
    
            if flag:
                comb_condition["%s__in" % key] = value_list
    
        querySet = self.model_class.objects.filter(self.get_cond_Q()).filter(**comb_condition).distinct()
        cl = ChangeList(self,querySet)
        return render(request, 'curd/changelist_view.html', {'cl':cl})
    
    • 前台页面
    <style>
        .list-filter a{
            display: inline-block;
            padding: 3px 6px;
            border: 1px solid #2e6da4;
            margin: 3px 0;
        }
        .list-filter a.active{
            background-color: #2e6da4;
            color: white;
        }
    </style>
    
    
    <!----------组合条件------------------>
    <div class="list-filter">
        {% for item in cl.gen_comb_filter %}
            <div>
            {% for col in item %}
                {{ col }}
            {% endfor %}
            </div>
        {% endfor %}
    </div>
    
    

    相关文章

      网友评论

          本文标题:基于curd的复合条件查询

          本文链接:https://www.haomeiwen.com/subject/pnbnwxtx.html