sixth_批量操作_多级过滤

 

 1.实现思想

致自己:所以的代码实现,都离不开两个基本:

  第一:如何拿到想要的对象。如果基础薄弱,或者不会搜索,那么这些方法,很难实现这一步;

  第二:如何操作想要操作的对象。当第一步实现后,那么如何操作,就需要有很强的逻辑及对代码块功能及类型清晰;

愿,我能一步登天

 

2.实现样式

 

3.代码部分

# sites
from django.urls import path, re_path
from django.shortcuts import HttpResponse, render, redirect
from app01 import models
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.core.exceptions import FieldDoesNotExist
from django.db.models import Q


class ShowList(object):
    def __init__(self, request, config_obj, queryset):
        self.request = request  # 请求对象
        self.config_obj = config_obj  # 当前调用者函数对象
        self.queryset = queryset  # 显示数据
        self.pager_queryset = self.get_pager_queryset()  # 分页机制

    def get_pager_queryset(self):
        from stark.utils.page import Pagination
        current_page = self.request.GET.get("page", 1)
        self.pagination = Pagination(self.request, current_page, self.queryset,
                                     per_page_num=self.config_obj.per_page_num or 5)
        queryset = self.queryset[self.pagination.start:self.pagination.end]  # 切片取展示的数据,到当前页
        # print("get_pager_queryset----queryset", queryset, type(queryset))
        return queryset

    def get_header(self):
        # 构建表头,将表头和表内数据分开成两个列表
        header_list = []
        for field_or_func in self.config_obj.get_new_list_display():
            # print("field_or_func", field_or_func)
            if callable(field_or_func):  # 判断是否可调用对象
                val = field_or_func(self, header=True)  # 将函数header改成True并调用得到值做表头
                header_list.append(val)  # 是的话调用函数并将值添加到表头
            else:
                if field_or_func == "__str__":
                    val = self.config_obj.model._meta.model_name.upper()
                else:
                    # app01.Book.title 取到对应models模型字段的对象
                    field_obj = self.config_obj.model._meta.get_field(field_or_func)
                    # 获取到对应表头名
                    val = field_obj.verbose_name
                header_list.append(val)
        return header_list

    def get_body(self):
        new_data = []
        for obj in self.pager_queryset:  # 将当前表数据循环获取出每一条的对象
            temp = []
            for field_or_func in self.config_obj.get_new_list_display():  # 循环新display列表, 并将内容取出来
                if callable(field_or_func):  # 如果是可调用对象
                    val = field_or_func(self.config_obj, obj)  # 运行函数并获取值
                else:
                    try:
                        from django.db.models.fields.related import ManyToManyField
                        field_obj = self.config_obj.model._meta.get_field(field_or_func)  # 获取到对象
                        # 判断是否多对多字段,判断该函数需要导入上面模块,如果直接写多对多则报错,需要自己写函数
                        if type(field_obj) == ManyToManyField:
                            raise Exception("list_display can't many To many")
                        # 判断字段是否拥有 choices 属性
                        if field_obj.choices:
                            # obj.get_state_display() 该方法能获取到choices对象目前的值
                            val = getattr(obj, "get_%s_display" % field_or_func)()
                        else:
                            # 所有对象空间如果有属性值,利用以下方法即可反射获取值
                            val = getattr(obj, field_or_func)
                            if field_or_func in self.config_obj.list_display_links:
                                # 如果有自定制link方法,则走下面这条语句,obj则是当前表的该条对象,link方法完成
                                val = mark_safe("<a href='%s'>%s</a>" % (self.config_obj.get_change_url(obj), val))
                    except FieldDoesNotExist as e:
                        # 进入publish时,走上面语句则会报错,就会进入下面这个方法
                        val = getattr(obj, field_or_func)()  # 直接用str获取当前对象的数据即可
                temp.append(val)  # 将数据一行一行的添加
            new_data.append(temp)
        # print("new_data", new_data)
        return new_data


class ModelStark(object):
    """
    默认配置类
    """
    list_display = ("__str__",)  # 创建一个变量,如果用户没有自定义则走默认的模型str(str在app01的models定义了),用来满足自定制
    list_display_links = []  # 点击书名等也可以进行编辑
    models_form_class = None  # 设定默认使用默认模板,进行添加编辑业务数据显示及添加修改
    per_page_num = None  # 定义默认指定显示数据为0
    search_fields = []  # 设定默认搜索区域即对象字段
    search_val = None  # 设置搜索跳转后,搜索框的内容
    list_filter = []  # 多级过滤
    actions = []  # 设置默认的批量

    def __init__(self, model):
        self.model = model
        self.model_name = self.model._meta.model_name  # 获取model名称
        self.app_label = self.model._meta.app_label  # 获取model所在app名称

    # 反向解析当前访问表的增删改查URL
    def get_list_url(self):
        # 反向解析当前表的URL
        list_url = reverse("%s_%s_list" % (self.app_label, self.model_name))
        return list_url

    def get_add_url(self):
        # 反向解析当前表的添加URL
        add_url = reverse("%s_%s_add" % (self.app_label, self.model_name))
        return add_url

    def get_delete_url(self, obj):
        # 反向解析当前表的删除URL,args 获取当前obj
        delete_url = reverse("%s_%s_delete" % (self.app_label, self.model_name), args=(obj.pk,))
        return delete_url

    def get_change_url(self, obj):
        # 反向解析当前表的编辑URL
        change_url = reverse("%s_%s_change" % (self.app_label, self.model_name), args=(obj.pk,))
        return change_url

    # 三个默认的列,即功能
    def show_checkbox(self, obj=None, header=False):
        """
        mark_safe: 将添加的字节进行编译,HTML默认将添加字节做字符串处理
        :param obj: None
        :param header: True
        :return:
        """
        if header:
            return mark_safe("<input type='checkbox'>")
        return mark_safe("<input name='_selected_action' value=%s type='checkbox'>" % obj.pk)  # 给box绑定对象pk值

    def show_delbtn(self, obj=None, header=False):
        if header:
            return "删除"
        return mark_safe("<a href='%s'>删除</a>" % self.get_delete_url(obj))

    def show_editbtn(self, obj=None, header=False):
        """
        mark_safe: 将添加的字节进行编译,HTML默认将添加字节做字符串处理
        :param obj: 当前表的对象
        :param header: 如果添加header命名则走自定制页面
        :return:
        """
        if header:
            return "编辑"
        return mark_safe("<a href='%s'>编辑</a>" % self.get_change_url(obj))

    # 构建新的list_display
    def get_new_list_display(self):
        temp = []
        temp.extend(self.list_display)  # 迭代增加元素,即将list_display拆开一个个添加进去
        temp.append(ModelStark.show_delbtn)  # 将删除模型类对象添加进去
        temp.append(ModelStark.show_editbtn)  # 将编辑模型类对象添加进去
        temp.insert(0, ModelStark.show_checkbox)  # 多选按钮插入到第0个位置
        """
        [<function ModelStark.show_checkbox at 0x0000025CCDED1C80>,
         'title', 'price', 'state', 'publisher',
        <function BookConfig.show_authors at 0x0000025CCDED1400>,
        <function ModelStark.show_delbtn at 0x0000025CCDED1D08>,
        <function ModelStark.show_editbtn at 0x0000025CCDED1D90>]
        """
        return temp  # 此时temp如上

    def get_search_condition(self, request):
        val = request.GET.get('q')
        from django.db.models import Q  # 导入过滤功能
        q = Q()  # 由于的Q不能接收字符串进行过滤,所以需要实例化q 来过滤
        if val:
            self.search_val = val
            q.connector = "or"  # 实例化q 只有且的功能,所以加上or
            for field in self.search_fields:
                q.children.append((field + "__contains", val))  # 拿出对应的搜索以元祖的形式添加
        else:
            self.search_val = None  # 如果前端搜索框没有请求,则清空内容,就不会自带着内容了
        # 返回搜索到的表的对象
        return q

    def patch_delete(self, request, queryset):
        # 设置默认的批量删除方法
        queryset.delete()

    patch_delete.desc = '批量删除'  # 给该函数添加desc对应的一个字符串

    def get_new_actions(self):
        """
        获取当前默认配置及自定制的批量操作方法
        :return:
        """
        temp = []
        temp.extend(self.actions)  # 添加是否有自定制的actions
        temp.append(self.patch_delete)  # 将默认批量删除方法导入
        # print("get_new_actions------->", temp, temp[0])
        return temp

    def get_action_dict(self):
        actions_list = []
        for func in self.get_new_actions():
            actions_list.append({
                'name': func.__name__,  # 获取批量操作函数
                'desc': func.desc,  # 获取批量操作名称
            })
        # print("get_action_dict-------->", actions_list)
        return actions_list

    def get_list_filter_links(self):
        """
        如何拿出相关url并放入返回到前端,
        深度拷贝get拿出单签url里的值params,利用.model._meta.get_field(字符串类型的字段名)的方法获取字段对应的表模型
        判断是否存在一对多,多对多的关系或者choices,仅对该情况进行处理,其它情况则不处理抛出错误(如:一对一)
        用表模型.remote_field.model.objects.all()的方法获得整个表的数据
        此时先进行对all(显示全部)的情况进行处理,url删除含有的当前对象字符串对应的键值对
        以下则是将其它键值对添加进去且逐个添加到a标签,并以字典的形式存放,前端提取即可
        :return:
        """
        list_filter_links = {}
        # print(self.list_filter)  # ['publisher', 'authors', 'state']
        for filter_field in self.list_filter:  # 循环多级过滤是否有设定,拿出字段
            import copy
            params = copy.deepcopy(self.request.GET)  # 深度拷贝,可修改
            current_field_val = params.get(filter_field)  # 当前循环url里面对象的值
            filter_field_obj = self.model._meta.get_field(filter_field)  # 获取字段对象
            # print("get_list_filter_links------>", filter_field_obj)  # app01.Book.publisher
            from django.db.models.fields.related import ForeignKey, ManyToManyField  # 导入一对多,多对多模型进行比较
            if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
                # print("获取整个表---->", filter_field_obj.remote_field.model)  # 该方法可以获取整个表 <class 'app01.models.Publish'>
                data = filter_field_obj.remote_field.model.objects.all()  # 获取整个表内数据<QuerySet [<Publish: 苹果出版社11>, <Publish: 橘子出版社>, <Publish: 西瓜出版社>, <Publish: 111>, <Publish: 西瓜出版社>]>

            elif filter_field_obj.choices:  # 如果是选择的字段类型
                data = filter_field_obj.choices
            else:
                raise Exception('过滤字段不能太简单!')
            # print(data)  # <QuerySet [<Author: A某>, <Author: B某>]> [(1, '已出版'), (2, '未出版')]
            # 为每一条数据构建一个a标签
            temp = []
            if params.get(filter_field):  # 如果all情况,存在该过滤字符串则删除该url字段
                del params[filter_field]
            # 为all 过滤 添加取除该段对象href
            all_content = "<a class='btn btn-default btn-sm' href='?%s'>显示所有</a>" % params.urlencode()
            temp.append(all_content)
            for item in data:
                if type(item) == tuple:
                    # 如果是元组类型,则是choice [(1, '已出版'), (2, '未出版')]
                    pk, text = item
                else:
                    # model对象类型
                    pk, text = item.pk, str(item)
                params[filter_field] = pk
                _url = '?%s' % (params.urlencode())
                if current_field_val:
                    if current_field_val == str(pk):
                        link = "<a class='active btn btn-default btn-sm' href='%s'>%s</a>" % (_url, text)
                    else:
                        link = "<a class='btn btn-default btn-sm' style='display:none' href='%s'>%s</a>" % (_url, text)
                    temp.append(link)
                else:
                    link = "<a class='btn btn-default btn-sm' href='%s'>%s</a>" % (_url, text)
                    temp.append(link)
                list_filter_links[filter_field] = temp
            print("-------list_filter_links", list_filter_links)
            # style='display:none'
        return list_filter_links

    def get_list_filter_condition(self):
        """
        一级搜索过滤
        :return:搜索完得到的Queryset
        """
        q = Q()
        for filter_field, val in self.request.GET.items():
            if filter_field in ['page', 'q']:
                continue
            q.children.append((filter_field, val))  # 搜索

        return q

    def list_view(self, request):
        """
        主要视图函数主要负责数据的首次显示,
        大部分调用都在这里
        :param request:
        :return:返回带数据的list视图
        """
        self.request = request
        # 处理批量函数
        if request.method == 'POST':
            action_func_str = request.POST.get('action')
            # print('action_func_str_list_view------->', action_func_str)
            if action_func_str:
                # 如果有,即选择非------的选项,则走以下语句
                action_func = getattr(self, action_func_str)  # 反射得到对应批量函数
                _selected_action = request.POST.getlist('_selected_action')  # 拿nid
                queryset = self.model.objects.filter(pk__in=_selected_action)  # 之间获取即可,这是orm的优化
                # print("action_func_str_if--------->", _selected_action, action_func, queryset)
                action_func(request, queryset)  # 该为函数调用,如果是默认即是调用patch_delete方法,执行完走以下语句即可

        queryset = self.model.objects.all()  # 获取当前对象的Queryset,即当前表数据
        # search 过滤
        search_condition = self.get_search_condition(request)  # 过滤及判断
        # list_filter多级过滤
        list_filter_condition = self.get_list_filter_condition()  # 先过滤判断出词条
        queryset = queryset.filter(search_condition).filter(list_filter_condition)  # 再进行多级过滤

        show_list = ShowList(request, self, queryset)  # 构建展示数据
        table_name = self.model._meta.verbose_name  # 当前表的名字
        add_url = self.get_add_url()  # 将add_url定义,此时local就会自动传到前端
        return render(request, 'stark/list_view.html', locals())

    def get_model_form(self):
        from django.forms import ModelForm  # 导入ModelForm模块,即将model 转化成form 的组件

        # 设定默认模板
        class BaseModelForm(ModelForm):
            # 设定默认模板,其中__all__
            class Meta:
                model = self.model  # 告诉ModelForm是关联哪张表
                fields = "__all__"  # 展示全部数据字段

        # 如果没有自定制则返回默认展示方式
        return self.models_form_class or BaseModelForm

    def add_view(self, request):
        base_model_form = self.get_model_form()  # 获取当前展示字段
        if request.method == "GET":
            form_obj = base_model_form()  # 获取当前展示字段并传到前端
            return render(request, 'stark/add_view.html', locals())
        else:
            form_obj = base_model_form(request.POST)
            if form_obj.is_valid():  # 判断用户输入的值是否符合model的规定
                form_obj.save()  # 如果符合则保存到数据库,并返回查看页面
                return redirect(self.get_list_url())
            else:
                return render(request, "stark/add_view.html", locals())  # 否则将携带报错信息的form返回当前页面提示用户

    def change_view(self, request, nid):
        base_model_form = self.get_model_form()  # 获取需要展示字段
        edit_obj = self.model.objects.filter(pk=nid).first()
        if request.method == 'GET':
            form_obj = base_model_form(instance=edit_obj)  # 这句话让modelform可以显示valus内容以供编辑
            return render(request, 'stark/change_view.html', locals())
        else:
            form_obj = base_model_form(request.POST, instance=edit_obj)  # instance 是告诉modelform是编辑,且编辑哪个对象
            if form_obj.is_valid():
                form_obj.save()
                return redirect(self.get_list_url())
            else:
                return render(request, 'stark/change_view.html', locals())

    def delete_view(self, request, nid):
        if request.method == 'POST':
            self.model.objects.filter(pk=nid).delete()
            return redirect(self.get_list_url())
        # 不删除则返回
        list_url = self.get_list_url()
        return render(request, 'stark/delete_view.html', locals())

    @property
    def get_urls(self):
        # 二级分发路径, 反向解析各种路径
        temp = [
            path("", self.list_view, name="%s_%s_list" % (self.app_label, self.model_name)),
            path("add/", self.add_view, name="%s_%s_add" % (self.app_label, self.model_name)),
            re_path("(\d+)/change/", self.change_view, name="%s_%s_change" % (self.app_label, self.model_name)),
            re_path("(\d+)/delete/", self.delete_view, name="%s_%s_delete" % (self.app_label, self.model_name)),
        ]

        return (temp, None, None)


class StarkSite:
    """
    stark 全局类
    """

    def __init__(self):
        # 类的单例模式,提高执行效率(都是用同一空间),减少开辟多个内存空间
        self._registry = {}

    def register(self, model, admin_class=None, **options):
        # model就是用户模型类(指向空间,即book或publish),admin_class 如果用户没有自己创建样式装修则用默认的
        admin_class = admin_class or ModelStark  # or 的方法,选择为非0的对象赋值
        self._registry[model] = admin_class(model)  # 给字典不断添加键值对,以model为键,配置类为值

    def get_urls(self):
        # 动态为注册的模型类创建增删改查URL
        # 创建temp存放path
        temp = []
        # {Book:ModelAdmin(Book),Publish:ModelAdmin(Publish)}
        for model, config_obj in self._registry.items():
            # 将上面函数拿到的各个模型类键值对提取出来,config_obj就是
            model_name = model._meta.model_name  # 该方法是拿model的名字(字符串)
            app_label = model._meta.app_label  # 该方法是拿model所在app的字符串
            """
            二级分发小例子:
            urls = [
                path('index/', index),
                path('book/',([
                    path('test01/', test01),
                    path('test02/', test02),
                ],None,None))
            ]
            """
            # 给temp添加path,即book_manage/book 或 book_manage/publishb
            # config_obj.get_urls 即是增删改查的路径(二级分发),默认就会有自己的二级temp
            temp.append(
                path("%s/%s/" % (app_label, model_name), config_obj.get_urls)
            )
        return temp

    @property
    def urls(self):
        # property 方法是使调用它的时候直接使用urls即可调用(默认Admin做的,可以参考urls里面的Admin)
        return self.get_urls(), None, None  # 调用时返回这些值,None是固定传的,一个是app名字一个是空间名字所以直接None


site = StarkSite()
"""
将全局类实例化成一个对象,所有的调用都使用这个实例化对象,
这样空间就永远是一个,只是实例化键值对来指向它
"""

 

# page
class Pagination(object):
    def __init__(self, request, current_page, all_data, per_page_num=3, max_page_count=11):
        """
        封装分页相关数据
        :param request: 请求对象
        :param current_page:当前页
        :param all_data: 总数据
        :param per_page_num: 每页显示的数据条数
        :param max_page_count: 最多显示的页码个数
        """

        try:
            current_page = int(current_page)  # 是否有跳转页
        except Exception as e:
            current_page = 1  # 没有则默认1
        # print("-------333", type(current_page))
        if current_page < 1:
            current_page = 1  # 如果为负,则默认1,容错机制

        self.current_page = current_page
        self.all_count = len(all_data)  # 获取总数据长度即有多少个对象
        self.per_page_num = per_page_num

        all_pager, tmp = divmod(self.all_count, per_page_num)  # 商除,取得商(显示多少页)和余(多出来的数据)
        if tmp:
            all_pager += 1  # 如果有多出来的数据,则页数+1
        # 定义数据便于调用
        self.all_pager = all_pager
        self.max_page_count = max_page_count
        self.max_page_count_half = int((max_page_count - 1) / 2)  # 最大显示页数的一半
        self.request = request
        import copy
        self.params = copy.deepcopy(self.request.GET)  # 深度拷贝,因为之间拿出来的Queryset是不能修改值的

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num  # 开始数

    @property
    def end(self):
        return self.current_page * self.per_page_num  # 结尾数

    def page_html(self):
        # 配置html页面
        if self.all_pager <= self.max_page_count:  # 如果总页码小于11个
            pageRange = range(1, self.all_pager + 1)
        else:  # 如果大于总页码,分以下3种情况
            # 如果当前页面小于页面上最多显示的(11-1)/2页码
            if self.current_page <= self.max_page_count_half:
                pageRange = range(1, self.max_page_count + 1)  #

            else:  # 如果当前页大于5,分以下两种情况
                if (self.current_page + self.max_page_count_half) > self.all_pager:
                    # 如果当前页数+5大于总页数,即已经翻到最后面了
                    pageRange = range(self.all_pager - self.max_page_count + 1, self.all_pager + 1)
                else:
                    # 当前页码即是处于中间位置
                    pageRange = range(self.current_page - self.max_page_count_half,
                                      self.current_page + self.max_page_count_half + 1)
        page_html_list = []  # 设置前端页面
        # 开始为首页和上一页添加a标签
        self.params["page"] = 1  # 页数为1
        first_page = '<nav aria-label="Page navigation"><ul class="pagination"><li><a href="?%s">首页</a></li>' % (
            self.params.urlencode(),)  # 首页跳转解析源码

        page_html_list.append(first_page)

        self.params['page'] = self.current_page - 1
        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'  # 如果小于等于1了,表名已经在第一页不能跳转了
        else:
            prev_page = '<li><a href="?%s">上一页</a></li>' % (self.params.urlencode())  # 否则

        page_html_list.append(prev_page)

        # 为每个数字页码添加a标签
        for i in pageRange:
            self.params['page'] = i
            if i == self.current_page:  # 如果页码刚好等于当前页面,则添加active 特殊样式
                temp = '<li class="active"><a href="?%s">%s</a></li>' % (self.params.urlencode(), i,)
            else:  # 否则添加普通样式即可
                temp = '<li><a href="?%s">%s</a></li>' % (self.params.urlencode(), i,)
            page_html_list.append(temp)  # 写入

        search_page = '<li><a href="?%s" id="search_id"><span aria-label="true">搜索</span</a></li> </ul></nav>' % (
            self.params.urlencode(),)
        # 为下一页和尾页添加a标签
        self.params['page'] = self.current_page + 1
        if self.current_page >= self.all_pager:  # 如果是最后一页,则添加不可点击特殊样式
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?%s">下一页</a></li>' % (self.params.urlencode())
        page_html_list.append(next_page)

        self.params['page'] = self.all_pager
        last_page = '<li><a href="?%s">尾页</a></li>' % (self.params.urlencode())
        page_html_list.append(last_page)

        val = self.request.GET.get('?')
        import copy
        params = copy.deepcopy(self.request.GET)  # 深度拷贝,可修改
        if not params:
            # 如果有使用字符搜索过滤等,则关闭页数搜索功能
            text_page = '<li><span><input type="text" id="text_id" style="height: 20px;width: 40px"></span></li>'
            page_html_list.append(text_page)

            page_html_list.append(search_page)
            script_page = '\n<script>' \
                          '\n\t$("#text_id").on("blur", function () {' \
                          '\n\t\tlet num = $("#text_id").val();' \
                          '\n\t\tlet a_obj = document.getElementById("search_id");' \
                          '\n\t\tconsole.log(num);' \
                          '\n\t\ta_obj.href ="?page=" + num;})\n' \
                          '\n</script>'
            page_html_list.append(script_page)
        return ''.join(page_html_list)  # 将所有代码拼接起来

 

# app01 stark
from stark.servise.sites import site, ModelStark
from .models import *
from django.forms import ModelForm


class BookModelForm(ModelForm):
    class Meta:
        model = Book
        fields = "__all__"
        error_messages = {
            "title": {"required": " 该字段不能为空!"}
        }


class BookConfig(ModelStark):

    def show_authors(self, obj=None, header=False):
        if header:
            return "作者信息"
        return " ".join([author.name for author in obj.authors.all()])

    # 自定制的模板,继承ModelStark,也就是还有没有覆盖的ModelStark变量及方法
    list_display = ["title", "price", "state", "publisher", show_authors]
    list_display_links = ['title', ]

    model_form_class = BookModelForm
    per_page_num = 3
    search_fields = ['title', 'price']
    list_filter=["publisher","authors","state"]

    def patch_init(self, request, queryset):
        queryset.updata(price = 0)
    patch_init.desc = '价格初始'


site.register(Book, BookConfig)  # 疑问,为什么执行了两遍
site.register(Publish)

# print(site._registry)

 

# list.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
    <script src="/static/bootstrap/js/jquery-3.3.1.js"></script>
    <link rel="stylesheet" href="/static/bootstrap/css/style.css">

    <script src="/static/bootstrap/js/jquery.min.js"></script>
    <script src="/static/bootstrap/js/script.js"></script>
    <style>
        .fixed {
            position: fixed;
            bottom: 40px;
            width: 100%;
            height: 50px;
            z-index: 9999;
        }
        .filter_body{
            padding-top: 8px;
            border-top:2px solid #a1a1a1;
            padding-bottom: 12px;
            border-bottom:2px solid #a1a1a1;
        }
        .filter_body .active {
            background-color: #3e8f3e;
            color: white;
        }
        div{
            margin-top: 10px
        }
        .content1:hover{
            background-color:lightgrey;
        }
    </style>

</head>
<body>
<div class="container">
    <div class="row">
        <span class="pull-left" style="height: 20px; font-size: 30px;margin-top: 30px">图书首页</span>
        <div class="panel-body panel-info">
            {% if show_list.config_obj.search_fields %}
                <form action="" method="get">
                    <div class="input-group pull-right" style="width: 400px">
                        <input value="{{ show_list.config_obj.search_val|default:'' }}" type="text" name="q"
                               class="form-control" placeholder="Search for...">
                        <span class="input-group-btn">
                        <button class="btn btn-primary">Search!</button>
                      </span>
                    </div>
                </form>
            {% endif %}
        </div>
            <div style="margin-top: 5px;">
                <div class="panel-default filter_body ">
                    {% for field,links in show_list.config_obj.get_list_filter_links.items %}
                        <div class="filter_body_item" style="margin-top: 5px">
                            <span class="btn btn-default btn-sm" style="width: 120px">按{{ field }}筛选</span>
                            {% for link in links %}
                                {{ link|safe }}
                            {% endfor %}

                        </div>
                    {% endfor %}
                </div>
            </div>
            <div>
            <div style="margin-top: 10px" class="pull-left">
                <a href="{{ add_url }}" class="btn btn-primary ">添加{{ table_name }}</a>
            </div>
                <form action="" method="post" class="input-group">
                    {% csrf_token %}
                    <div class="action" style="margin-top: 10px; margin-left: 10px">
                        <select class='form-control' name="action" id=""
                                style="width: 250px;display: inline-block;vertical-align: -2px;">
                            <option value="">--------------</option>
                            {% for action in show_list.config_obj.get_action_dict %}
                                <option value="{{ action.name }}">{{ action.desc }}</option>
                            {% endfor %}
                        </select>
                        <button class="btn btn-primary" style="margin-left: -4px">GO</button>
                    </div>

            </div>

        <table class="table" id="">
            <thead>
            <tr>
                {% for item1 in show_list.get_header %}
                    <th>{{ item1 }}</th>
                {% endfor %}
            </tr>

            </thead>
            <tbody>
            {% for item in show_list.get_body %}
                <tr  class="content1">
                    {% for info in item %}
                        <td>{{ info }}</td>
                    {% endfor %}
                </tr>
            {% endfor %}
            </tbody>
        </table>
        <div class="pull-right">
            {{ show_list.pagination.page_html|safe }}
        </div>
    </form>
    </div>
</div>
<div style="position:fixed; bottom:0;"></div>
<div class="wave-box fixed">

    <div class="marquee-box marquee-up" id="marquee-box">
        <div class="marquee">
            <div class="wave-list-box" id="wave-list-box1">
                <ul>
                    <li><img height="60" alt="波浪" src="/static/bootstrap/images/wave_02.png"></li>
                </ul>
            </div>
            <div class="wave-list-box" id="wave-list-box2">
                <ul>
                    <li><img height="60" alt="波浪" src="/static/bootstrap/images/wave_02.png"></li>
                </ul>
            </div>
        </div>
    </div>

    <div class="marquee-box" id="marquee-box3">
        <div class="marquee">
            <div class="wave-list-box" id="wave-list-box4">
                <ul>
                    <li><img height="100" alt="波浪" src="/static/bootstrap/images/wave_01.png"></li>
                </ul>
            </div>
            <div class="wave-list-box" id="wave-list-box5">
                <ul>
                    <li><img height="100" alt="波浪" src="/static/bootstrap/images/wave_01.png"></li>
                </ul>
            </div>
        </div>
    </div>

</div>
</body>
</html>

 

完成

posted @ 2019-04-18 22:08  pythonernoob  阅读(91)  评论(0)    收藏  举报