美文网首页
基于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