• Xadmin显示视图


    .display显示要设置的字段

    1. 自定义样式类,显示出要显示的字段,在这个类中,也可以设置对应函数。 list_display=[check,"title",delete]
    2.在 Modelxadmin中设置:list_display=["__str__"]
    设置Modelxadmin的静态属性,即当注册的对象没使用样式类时,使用Modelxadmin的样式属性
    3.处理表头
    display中的函数名或者变量名作为表头
    1.需要判断传的列表中的内容是函数名还是字符串
    2.如果是字符串,判断是"__str__"还是其他的
    3.让相应的字符串表头显示对应的中文,取到字段对象,引用字段中的verbose_name
    4.处理表单数据
    需要判断传的列表中的内容是函数名还是字符串
    1.若是函数名,去执行对应的函数,取到对应的值
    2.若是变量,利用反射到相应的数据中取到值

    2.设定样式类list_display

    from Xadmin.service.Xadmin import site,Modelxadmin
    from app01 import models
    from django.utils.safestring import  mark_safe
    class BookConfig(Modelxadmin):
        href=change/'%s/'自动在当前路径后拼接路径
        def edit(self, obj=None,  is_header=False):
            if is_header:  # 此时作表头处理
                return "操作"
            return mark_safe("<a href='change/%s/'>编辑</a>"%obj.pk)
        def delete(self, obj=None, is_header=False):
            if is_header:  # 此时作表头处理
                return "删除"
            return mark_safe("<a href='del/%s/'>删除</a>" % obj.pk)
        def check(self, obj=None, is_header=False):
            if is_header:  # 此时作表头处理
                return "选择"
            return mark_safe("<input type='checkbox'>")
        list_display=[check,"title","price","publish","authors",edit,delete]
    site.register(models.Book,BookConfig)
    View Code

    3.显示设置

    1.处理表头

    处理表头 [check,'title', 'prcie',edit]
    # 1.需要判断传的列表中的内容是函数名还是字符串
    # 2.如果是字符串,判断是"__str__"还是其他的
     head=[]
            for field in self.list_display:
                if isinstance(field,str):
                   if field=="__str__":
                       val=self.model._meta.model_name.upper()  #如果没定义样式类,表头就显示操作表的名字的大写
                   else:
                       # class Book(models.Model):
                       #     title = models.CharField(max_length=32, verbose_name="书名")
                       #     price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="价格")
                       #如果是字段字符串,让表头显示其定义的中文表头。title是字段对象,找到title后title.verbose_name 获取这个属性值
                       obj=self.model._meta.get_field(field)
                       val=obj.verbose_name
                else:
                    val = field(self,is_header=True)
                head.append(val)
    View Code

    2.处理表单数据

    使用反射
            data_list=self.model.objects.all() #取出每一条数据的对象,data_list[0].字段名(title) 就能得到相应的数据
            content = []
            for obj in data_list:
                temp=[]
                for field in self.list_display:#自定义的样式类中有可能放的是自定义的函数名[check,'title', 'prcie',edit]
                    #需要判断传的列表中的内容是函数名还是字符串
                    if isinstance(field,str): #判断数据类型
                       val=getattr(obj,field)  #相当于obj.title,obj.price 其中obj.__str__会自动触发这个方法
                       print("结果是:",val)
                    else:
                        val=field(self,obj,) #定义的方法,obj为这个方法执行的哪条数据对象
                    temp.append(val)
                content.append(temp)
            return render(request,"list.html",{"content":content,"head":head,"type":type})
    View Code

    4.利用反向路由解析得到路径

    '''
    #Modelxadmin中设置
    class Modelxadmin(object):
        list_display=["__str__"] #设置Modelxadmin的静态属性,即当注册的对象没使用样式类时,使用Modelxadmin的样式属性
        def __init__(self,model,site):  #如果传的是book,model就是Book 传的是publish,model就是Publiah
            self.model=model
            self.site=site
            self.model_name = self.model._meta.model_name #得到app名
            self.app_name = model._meta.app_label  #得到表名
            #为路由设置别名:
                def get_url_2(self):
            temp = []
            # print("=====",model_name )
            # temp.append(url(r"^$", self.list_view))
            temp.append(url(r"^$", self.list_view,name="{}/{}_list".format( self.app_name, self.model_name)))
            temp.append(url(r"^add/$", self.add_view,name="{}/{}_add".format( self.app_name, self.model_name)))
            # temp.append(url(r"^(d+)/change/$", self.change_view,))
            temp.append(url(r"^change/(d+)/$", self.change_view,name="{}/{}_change".format( self.app_name, self.model_name) ))
            temp.append(url(r"^del/(d+)/$", self.del_view,name="{}/{}_del".format( self.app_name, self.model_name)))
            return temp
    #自定以样式类中设置:
    from django.utils.safestring import  mark_safe
    from django.urls import reverse
    class BookConfig(Modelxadmin):
        def edit(self, obj=None,  is_header=False):
            if is_header:  # 此时作表头处理
                return "操作"          #BookConfig中没有self.app_name,就去Modelxadmin找
            url_name="{}/{}_change".format( self.app_name, self.model_name)
            v = reverse(url_name, args=(obj.pk,))
            return mark_safe("<a href='%s'>编辑</a>" % v)
    '''
    View Code

    显示页面的html

    '''
    <p>
        <span>序号</span>
        {% for foo in head %}
            <span>{{ foo }}</span>
        {% endfor %}
    </p>
    
    {% for foo in content %}
        <P>
          <span>{{ forloop.counter }}</span>
          {% for foo1 in foo %}
           <span>{{ foo1 }}</span>
        {% endfor %}
        </P>
    {% endfor %}
    '''

    5.显示多对多的关系字段

    多对多的字段,传过去之后在页面上显示字符串:app01.Author.None
    例:作者是多对多的关系
     list_display=[check,"title","price","publish","authors",edit,delete]
     传过去之后在页面上显示字符串:app01.Author.None
    解决方法一:将ManytoMany这个字段当作函数名传过去,不再写成字符串
    在样式类中定义ManytoMany字段方法:
        def display_authors(self,obj=None, is_header=False):
            if is_header:
                return "作者名称"
            s=[]
            for author in obj.authors.all(): #必须使用all(),得到所有的作者对象
                s.append(author.name) #取出每个作者对象的name属性
            val=" | ".join(s)
            return mark_safe(val)
    
        list_display = [check, "title", "price", "publish", display_authors, edit, delete]
    方法二:判断是不是ManytoMany类型
            data_list=self.model.objects.all() #取出每一条数据的对象,data_list[0].字段名(title) 就能得到相应的数据
            content = []
            for obj in data_list:
                temp=[]
                for field in self.list_display:#自定义的样式类中有可能放的是自定义的函数名[check,'title', 'prcie',edit]
                    #需要判断传的列表中的内容是函数名还是字符串
                    if isinstance(field,str): #判断数据类型
                        #处理多对多的字段方法二:判断是不是ManytoMany类型
                        from django.db.models.fields.related import ManyToManyField
                        many_obj = self.model._meta.get_field(field) #取到字段对象
                        if isinstance(many_obj,ManyToManyField):
                            t=[]
                            for i in getattr(obj,field).all():
                                t.append(i.name)
                            val=" | ".join(t)
                        else:val=getattr(obj,field)  #相当于obj.title,obj.price 其中obj.__str__会自动触发这个方法
    list_display=[check,"title","price","publish","authors",edit,delete]
    View Code

    6.将删除,编辑,选择按钮封装起来

    '''
    app01.Xadmin 
    1.使用继承:但是需要在每个样式类中设定
    class Operation():
        def edit(self, obj,is_header):
            if is_header:  # 此时作表头处理
                return "操作"
            else:
                url_name = "{}/{}_change".format(self.app_name, self.model_name)  # BookConfig中没有self.app_name,就去Modelxadmin找
                v = reverse(url_name, args=(obj.pk,))
                return mark_safe("<a href='%s'>编辑</a>" % v)
        def delete(self, obj, is_header):
            if is_header:  # 此时作表头处理
                return "操作"
            return mark_safe("<a href='del/%s/'>删除</a>" % obj.pk)
    
        def check(self, obj, is_header):
            if is_header:  # 此时作表头处理
                return "选择"
            else:print(777)
            return mark_safe("<input type='checkbox'>")
    class BookConfig(Modelxadmin, Operation):
        def check(self,obj=None, is_header=False):return super().check(obj, is_header)
        def edit(self,obj=None, is_header=False):return super().edit(obj, is_header)
        def delete(self,obj=None,  is_header=False):return super().delete(obj, is_header)
        list_display=[check,"title","price","publish","authors",edit,delete]
    #如果不在BookConfig中定义check,edit,delete函数,在list_dispaly中加函数名后,会显示未定义。在用super调用时不能传位置参数
    2.在Xadmin中设置,将check,edit,delete加到每个模型表的样式类中,模型表的样式类就不用再加这些函数
    class Modelxadmin(object):
        # 选择按钮  编辑 删除
        def edit(self, obj=None, is_header=False):
            if is_header:  # 此时作表头处理
                return "操作"
            else:
                v=self.get_change_url(obj)
                return mark_safe("<a href='%s'>编辑</a>" %v)
        def delete(self, obj=None, is_header=False):
            if is_header:  # 此时作表头处理
                return "操作"
            v = self.get_del_url(obj)
            return mark_safe("<a href='%s'>删除</a>" %v)
        def check(self, obj=None, is_header=False):
            if is_header:  # 此时作表头处理
                return "选择"
            v = self.get_del_url(obj)
            return mark_safe("<input type='checkbox'>")
        #构建新的list_dispaly
        def new_list_display(self):
            temp=[]
            temp.append(Modelxadmin.check)
            temp.extend(self.list_display)
            temp.append(Modelxadmin.edit)
            temp.append(Modelxadmin.delete)
            return temp
        #处理表头 [check,'title', 'prcie',edit]
        for field in self.new_list_display():pass
         #处理表单数据,使用反射
          data_list=self.model.objects.all() #取出每一条数据的对象,data_list[0].字段名(title) 就能得到相应的数据
            content = []
            for obj in data_list:
                temp=[]
                for field in self.new_list_display():pass
    样式类中直接传要显示的字段 list_display = ["title", "price", "publish", "authors"]
    '''
    View Code

    7.设定样式类list_display_link

    1.在循环表单数据时,如果list_display中的字段名在list_display_link,就将改字段的内容设置成编辑标签
    2.如果表中数据设置成了编辑标签,那么编辑这个操作就没什么用了,应该判断如果样式中无list_display_link,就显示编辑操作,
    有list_display_link则不显示编辑操作
    在new_list_display中判断是否加编辑操作
        def new_list_display(self):
            temp=[]
            temp.append(Modelxadmin.check)
            temp.extend(self.list_display)
            #判断是否加编辑操作
            if not self.list_display_link:
                temp.append(Modelxadmin.edit)
            temp.append(Modelxadmin.delete)
            return temp
    ##将相应值设置成编辑标签
    from django.db.models.fields.related import ManyToManyField
        try:
            many_obj = self.model._meta.get_field(field) #取到字段对象
            if isinstance(many_obj,ManyToManyField):
                t=[]
                for i in getattr(obj,field).all():
                    t.append(i.name)
                val=" | ".join(t)
            else:
                #判断改字段是否在list_display_link,如果在,就设置成标签形式,不再就正常显示
                if field in self.list_display_link:
                    edit_url=self.get_change_url(obj)
                    val=mark_safe("<a href='%s'>%s</a>"%(edit_url,getattr(obj,field)))
                else:val=getattr(obj,field)
        except Exception as e:
            val = getattr(obj, field)
    View Code
    显示页面的函数形式
    '''
     def list_view(self, request): #self是Modelxadmin的实例对象,要么是自定义样式类的实例对象
        # print("这里是:", model_name )
        type=request.GET.get("name")
        if not type:type=""
        print(type)
        print(self.model)  #用户调用的哪张表,self.model就是哪张表  <class 'app02.models.Order'>
        print("新的是:",self.new_list_display())
        #处理表头 [check,'title', 'prcie',edit]
        # 1.需要判断传的列表中的内容是函数名还是字符串
        # 2.如果是字符串,判断是"__str__"还是其他的
        head=[]
        # for field in self.list_display:
        for field in self.new_list_display():
            if isinstance(field,str):
               if field=="__str__":
                   print("食物")
                   val=self.model._meta.model_name.upper()  #如果没定义样式类,表头就显示操作表的名字的大写
               else:
                   # class Book(models.Model):
                   #     title = models.CharField(max_length=32, verbose_name="书名")
                   #     price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="价格")
                   #如果是字段字符串,让表头显示其定义的中文表头。title是字段对象,找到title后title.verbose_name 获取这个属性值
                   obj=self.model._meta.get_field(field)
                   val=obj.verbose_name
            else:
                val = field(self,is_header=True)
            head.append(val)
            print(head)
        #处理表单数据,使用反射
        data_list=self.model.objects.all() #取出每一条数据的对象,data_list[0].字段名(title) 就能得到相应的数据
        content = []
        for obj in data_list:
            temp=[]
            # for field in self.list_display:#自定义的样式类中有可能放的是自定义的函数名[check,'title', 'prcie',edit]
            for field in self.new_list_display():
                #需要判断传的列表中的内容是函数名还是字符串
                if isinstance(field,str): #判断数据类型
                    #处理多对多的字段方法二:判断是不是ManytoMany类型
                    from django.db.models.fields.related import ManyToManyField
                    try:
                        #如果是__str__ 走到这会报错,因此使用抛出异常处理
                        many_obj = self.model._meta.get_field(field) #取到字段对象
                        if isinstance(many_obj,ManyToManyField):
                            t=[]
                            for i in getattr(obj,field).all():
                                t.append(i.name)
                            val=" | ".join(t)
                        else:
                            # val=getattr(obj,field)  #相当于obj.title,obj.price 其中obj.__str__会自动触发这个方法
                            #判断改字段是否在list_display_link,如果在,就设置成标签形式,不再就正常显示
                            if field in self.list_display_link:
                                edit_url=self.get_change_url(obj)
                                val=mark_safe("<a href='%s'>%s</a>"%(edit_url,getattr(obj,field)))
                            else:val=getattr(obj,field)
                    except Exception as e:
                        val = getattr(obj, field)
                    print("结果是:",val)
                else:
                    val=field(self,obj,) #定义的方法,obj为这个方法执行的哪条数据对象
                temp.append(val)
                print("temp是:", temp)
            content.append(temp)
        print("content是:", content)
        # ##获取增加页面的url 点击增加的时候,跳到增加页面。自动拼接
        # add_url="add"
        return render(request,"list.html",{"content":content,"head":head,"type":type,"add_url":self.get_add_url()})
    
    
    
    '''
    View Code

    8.设置分页

    将分页方法设置为显示类得属性,用时直接用对象调用

    class ShowList(object):
        def __init__(self,config,data_list,request):
            self.config=config  #config是Modelxadmin的对象
            self.data_list=data_list
            self.request=request
        ##配置分页设置:
            current_page = self.request.GET.get("page")
            pagination = Pagination(current_page, self.data_list.count(), "%s" % self.config.get_list_url(), self.request.GET,
                                    per_page_num=3)
            self.pagination=pagination
            self.model_list = self.data_list[pagination.start:pagination.end]
     def get_body(self):
            content = []
            for obj in self.model_list:pass #循环分完页之后数据对象
    View Code
    分页条:
    <ul class="pull-right">
    {{show_list.pagination.page_html|safe }}
    </ul>

    9.搜索功能

    搜索时用GET请求,后端很根据收到的搜索条件进行处理,在显示全部数据的基础上,将符合搜索的内容显示出来
    未使用搜索时,获得当前对象的所有内容
    data_list = self.model.objects.all()
    加了搜索,就在这基础上进行条件搜索,使用filter
    data_list = self.model.objects.filter(条件)
    获取到设定的搜索字段,使用Q()进行操作,将字符串类型的字段和接受到的搜索值加到Q()中,搜索时会检测所有对象的这个字段中是否含有搜索值,如果有,就把这个
    对象取出来
    class Modelxadmin(object):
        search_fields = []
        def get_search(self, request):
            search_condition = Q()
            search_condition.connector = 'or'
            search_value = request.GET.get("search_value")
            if search_value:
                for search_field in self.search_fields:
                    search_condition.children.append((search_field + "__icontains", search_value))
            return search_condition
        def list_view(self, request): #self是Modelxadmin的实例对象,要么是自定义样式类的实例对象
            #print(self.model)  #用户调用的哪张表,self.model就是哪张表  <class 'app02.models.Order'>
            search_condition=self.get_search(request)
            data_list = self.model.objects.filter(search_condition) #search_condition有值,就按值搜索,无值就搜索全部
    Views.py
    在显示页面,设置搜索框是否显示。通过判断search_fields来判断是都设置了搜索值,如果为空,在页面上就不显示搜索
    HTML
    '''
    {% if  show_list.config.search_fields %}
     <div class="input-group">
         <form action=" " method="GET">
            <span class="input-group-btn">
                 <input type="text" name="search_value" class="form-control" placeholder="Search for...">
                <button class="btn btn-default" >搜索</button>
            </span>
         </form>
     </div>
    {% endif %}
    '''
    View Code

    10.批处理功能

    实现选择对应得操作后,执行对应得函数
    批处理操作使用select选择的方式:value应对应函数名,显示的操作名称不应该直接再HTML中设定,
    可以在后端为相应的执行函数起相应的名字
    对函数做描述:
    foo.short_description="批量初始化" #对这个函数作描述
    class A():
        def foo(self,queryset):
            queryset.delete()
        foo.short_description="批量删除"
        def update(self,queryset):
            queryset.update(price=100)
        update.short_description="批量初始化"  #对这个函数作描述
        action=[foo,update]
    b=A()
    for i in b.action:   #i是函数名
        print(i.__name__,i.short_description)
    HTML中
      <option value="{{ i.__name__ }}">{{ i.short_description) }}</option>
    View Code

    1.设置批处理函数

    在app01 Xadmin中设置自定义处理函数:
    class BookConfig(Modelxadmin):
     def all_update(self,request,queryset): #queryset为数据对象
            queryset.update(price=998)
            list_url = self.get_list_url()
            return redirect("%s" % list_url)
        all_update.short_description="批量初始化"
        actions=[all_update,]
    在全局中设置批量删除函数:
    class Modelxadmin(object):
    actions=[]
      def all_delete(self,request,queryset):
            queryset.delete()
            list_url=self.get_list_url()
            return redirect("%s"%list_url)
        all_delete.short_description="批量删除"

    2.在Modelxadmin将批量删除和样式类中的actions合到一起

    def get_action(self): #将批量删除和样式类中的actions合到一起
            temp=[]
            temp.append(self.all_delete)
            temp.extend(self.actions) #迭代添加
            return temp  
    #将得到的temp作为ShowList的一个属性,并函数名和描述值处理后在页面显示出来
    class ShowList(object):
    self.actions=self.config.get_action()
    def new_actions(self):
        temp=[]
        for action in self.actions:
            temp.append({
                "name":action.__name__,
                "desc":action.short_description
            })
        return temp
    View Code

    3.HTML

    <span class="input-group-btn" >
        <select name="action" id="" class="form-control">
            <option value="">------------------</option>
            {% for foo in show_list.new_actions %}
                 <option value="{{ foo.name }}">{{foo.desc  }}</option>
            {% endfor %}
        </select>
        <button class="btn btn-default" >GO</button>
    </span>

    4.后台接收处理:

    class Modelxadmin(object):
         def list_view(self, request):
              if request.method=='POST': #批量操作
                    action=request.POST.get("action")  #哪种操作,name="action",值为要执行操作的函数名
                    print("操作是",action)
                    selected_pk=request.POST.getlist("selected") #操作的数据
                    action_obj=self.model.objects.filter(pk__in=selected_pk)
                    action=getattr(self,action)
                    ret=action(request,action_obj)
                    return ret

    完整的views.py

    ##批处理:得到注册对象样式类中指定的操作,并为所有的注册对象添加上删除操作
    def all_delete(self,request,queryset):
        queryset.delete()
        list_url=self.get_list_url()
        return redirect("%s"%list_url)
    all_delete.short_description="批量删除"
    def get_action(self): #将批量删除和样式类中的actions合到一起
        temp=[]
        temp.append(self.all_delete)
        temp.extend(self.actions) #迭代添加
        return temp  #将得到的temp作为ShowList的一个属性
    def list_view(self, request): #self是Modelxadmin的实例对象,要么是自定义样式类的实例对象
        if request.method=='POST': #批量操作
            action=request.POST.get("action")  #哪种操作
            print("操作是",action)
            selected_pk=request.POST.getlist("selected") #操作的数据
            action_obj=self.model.objects.filter(pk__in=selected_pk)
            action=getattr(self,action)
            ret=action(request,action_obj)
            return ret
    View Code

    11.过滤功能

    1.首先在页面上展示出过滤的内容

    页面收到后端传来的数据进行循坏操作,收到的应该是个字典:
    {"publish":["a","a"],"author":["a","a"]},key值为表名,value为表中的所有对象的名字,同时将value
    设置成标签,herf设为?key=obj.pk的形式,点完标签后,后台接受到操作的表名和要操作的对象进行搜索操作,从而展示出来

    2.在指定的app01中注册模型表中设置过滤的字段:以Book表为例:

    class BookConfig(Modelxadmin):
        list_filter=["publish","authors"]
    在Xadimn中作后台处理操作:
    class Modelxadmin(object):
          list_filter = []
    
    
    首先要做的是创建出{"publish":["a","a"],"author":["a","a"]}这种类型给页面展示出来,展示出来之后,在做跳转操作,展示的处理都放在
    ShowList中,在ShowList中定义处理函数。得到自定义的search_fields中,得到对应的字符串类型的字段,根据字符串,找到这个字段对象,根据字段
    对象,得到关联表中的所有对象,将这个对象名做成链接返给页面
    1.def get_filter_link_tags(self):
        # link_tags={"publish":["a","a"],"author":["a","a"]}
        link_tags={}
        for filter_field in self.list_filter: #["title", "price"]
            filter_field_obj=self.config.model._meta.get_field(filter_field) #得到Book表中的publish和authors字段
            #得到字段对象关联表的所有对象。publish和authors中所有对象
            related_data_list=filter_field_obj.rel.to.objects.all()
            temp=[]
            for obj in related_data_list: #对每个对象做处理
                _url="%s=%s"%(filter_field,obj.pk)
                s="<a href='?%s'>%s</a>"%(_url,str(obj)) #在页面显示出?publish=2
                temp.append(mark_safe(s))
            link_tags[filter_field]=temp
        return link_tags

    3.点击相应链接

    在点击相应链接之后,点击publish中的对象显示?publish=2这种形式,点击author中的内容显示?author=2
    但是要保存搜索条件,即在上次选的条件下继续搜索,达到?publish=2&?author=2的效果。使用request.GET
    在第一次点击链接之后,页面刷新,会重新走到这一步,获取数据返还给页面,此时self.request.GET获取到?publish=2,在执行到循环authors的对象时
    就会将参数拼接起来?publish=2&?author=2
    def get_filter_link_tags(self):
            # link_tags={"publish":["a","a"],"author":["a","a"]}
            link_tags={}
            from copy import deepcopy
            for filter_field in self.list_filter:
              # /Xadmin/app01/book/?page=2
                params = deepcopy(self.request.GET)  #将后面的参数以字典的形式接收 {'page':2}
                filter_field_obj=self.config.model._meta.get_field(filter_field)
                #得到字段对象关联表的所有对象
                related_data_list=filter_field_obj.rel.to.objects.all()
                temp=[]
                for obj in related_data_list:
                    params[filter_field]=obj.pk # {"authors":2}
                    _url=params.urlencode()
                    # _url="%s=%s"%(filter_field,obj.pk)
                    s="<a href='?%s'>%s</a>"%(_url,str(obj))
                    temp.append(mark_safe(s))
                    link_tags[filter_field]=temp
            return link_tags
    View Code

    4.点击完当前标签之后,当前标签添加背景色。通过判断当前的接受到的id和循环中的当前id是否相等

    current_id=self.request.GET.get(filter_field)
    if current_id==str(obj.pk):
            s = "<a class='item' href='?%s'>%s</a>" % (_url, str(obj))
    else:  
        s="<a href='?%s'>%s</a>"%(_url,str(obj))

    5.链接跳转

    点击相应的标签后,后台接收到?publish=2这个数据,进行过滤查询,使用Q().children
    class Modelxadmin(object):
        filter_condition=Q()
        for filter_field,val in request.GET.items():
            ##当选择分页时,页面上会把page=2传过来,仍走这一步,但是表中并没有这个字段,所以会报错
            if filter_field not in ['page',"search_value"]:
                filter_condition.children.append((filter_field,val))
        data_list = self.model.objects.filter(filter_condition).filter(search_condition) #search_condition有值
    View Code

    过滤功能views.py

    class BookConfig(Modelxadmin):
        list_filter=["publish","authors"]
        
    class Modelxadmin(object):
          list_filter = []
          def list_view(self, request): 
           filter_condition=Q()
            for filter_field,val in request.GET.items():
                ##当选择分页时,页面上会把page=2传过来,仍走这一步,但是表中并没有这个字段,所以会报错
                if filter_field not in ['page',"search_value"]:
                    filter_condition.children.append((filter_field,val))
            data_list = self.model.objects.filter(filter_condition).filter(search_condition)
             #search_condition有值,就按值搜索,无值就搜索全部
    class ShowList(object):
     def get_filter_link_tags(self):
            # link_tags={"publish":["a","a"],"author":["a","a"]}
            link_tags={}
            from copy import deepcopy
            for filter_field in self.list_filter:
                # /Xadmin/app01/book/?page=2
                params = deepcopy(self.request.GET)#将后面的参数以字典的形式接收 {'page':2}
                current_id=self.request.GET.get(filter_field)
                filter_field_obj=self.config.model._meta.get_field(filter_field)
                #得到字段对象关联表的所有对象
                related_data_list=filter_field_obj.rel.to.objects.all()
                temp=[]
                for obj in related_data_list:
                    params[filter_field]=obj.pk # {"authors":2}
                    _url=params.urlencode()
                    # _url="%s=%s"%(filter_field,obj.pk)
                    if current_id==str(obj.pk):
                        s = "<a class='item' href='?%s'>%s</a>" % (_url, str(obj))
                    else:  
                        s="<a href='?%s'>%s</a>"%(_url,str(obj))
                    temp.append(mark_safe(s))
                link_tags[filter_field]=temp
            return link_tags
            
    HTML:
     <div class="col-sm-2">
                {% for filter_filed,link_tag_list in show_list.get_filter_link_tags.items  %}
                    <p>By {{ filter_filed.upper }}</p>
                    {% for link_tag in link_tag_list  %}
                    <p>{{ link_tag }}</p>
                    {% endfor %}
                {% endfor %}
    
            </div>
    View Code
     
  • 相关阅读:
    使用npm安装一些包失败了的看过来(npm国内镜像介绍)(解决生成空的abp模板项目一直卡在还原cpm包中)
    .NET CORE 发布到IIS问题 HTTP ERROR 500.30
    .NET Core默认不支持GB2312,使用Encoding.GetEncoding(“GB2312”)的时候会抛出异常。
    .net c# 文件分片/断点续传之下载--客户端
    aspnetcore 实现断点续传
    C# 反射获取属性值、名称、类型以及集合的属性值、类型名称
    C# 3Des两种加密方式 (对应java中的desede/CBC/PKCS5Padding加密)
    Asp.NetCore3.1中多次读取Request.Body
    ASP.NET Core 2.0系列学习笔记-DI依赖注入
    C# Newtonsoft.Json JObject合并对象整理
  • 原文地址:https://www.cnblogs.com/chongdongxiaoyu/p/9177755.html
Copyright © 2020-2023  润新知