博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Xadmin查询
阅读量:5055 次
发布时间:2019-06-12

本文共 13467 字,大约阅读时间需要 44 分钟。

目录

目录

深浅coopy运用

为什么在类中引用函数不用self 而是用类名调用

def search_boutton(self,obj=None,header=False):        if header:            return "操作"        else:            url = reverse("%s_%s_update"%(self.app_name,self.table_name),args=[obj.pk,])      # 反向解析            return mark_safe("编辑" % url)                   def rebulid_display_list(self):        tem=[]        tem.append(ModelXadmin.checkbox_button)         # 把选择框加到表头和表单前面,               # 之所以用类,是因为在缺省形参中,如果调用一次,之后的参数都会发生改变,        tem.extend(self.list_display)     # 把实例化对象自身的数据加到tem当中        if not self.list_display_link:     # 是否传有link项            tem.append(ModelXadmin.search_boutton)        tem.append(ModelXadmin.delete_button)         # 把选择框加到表头和表单前面,        return tem

这是因为函数中有缺省参数,如果 用self调用,就会指向自己的方法内,缺省参数有一次改变,之后的调用都是指向该值,即参数会改变,而函数则是不一样,他的缺省参数,默认的是原始值.

ModelForm的补充

def get_models_form(self):        if not self.Model_Form_class:            class Model_Form(ModelForm):                class Meta:                    model = self.model                    fields = "__all__"                    labels = {                        ""                    }            return  Model_Form      # 查看列表,即主页,并对相应字段配上路径        else:            return self.Model_Form_class

提取模型当中相关属性

getattr和get_field的区别

getattr主要是提取对象当中的属性,切记是对象属性

class Article(models.Model):    """    文章    """    nid = models.AutoField(primary_key=True)    title = models.CharField(max_length=50, verbose_name="文章标题")  # 文章标题    desc = models.CharField(max_length=255,verbose_name="文章简述")  # 文章描述    create_time = models.DateTimeField(verbose_name="创建时间",auto_now_add=True)  # 创建时间    # 评论数    comment_count = models.IntegerField(verbose_name="评论数", default=0)    # 点赞数    up_count = models.IntegerField(verbose_name="点赞数", default=0)    # 踩    down_count = models.IntegerField(verbose_name="踩数", default=0)    category = models.ForeignKey(to="Category", to_field="nid", null=True ,on_delete=models.CASCADE,verbose_name="分类")    user = models.ForeignKey(to="UserInfo", to_field="nid" ,on_delete=models.CASCADE,verbose_name="作者")    tags = models.ManyToManyField(  # 中介模型        to="Tag",        through="Article2Tag",        through_fields=("article", "tag"),  # 注意顺序!!!        verbose_name="标签",    )    def __str__(self):        return self.title    class Meta:        verbose_name = "文章"        verbose_name_plural = verbose_name

如下测试

obj=models.Article.objects.filter(user=12).first()   print("nid:",type(getattr(obj,"nid")))print("title:",type(getattr(obj,"title")))print("user:",type(getattr(obj,"user")))----------------------------------------结果是:nid: 
title:
user:

也就是说其拿到的是对象的属性,如果是外键,也可以理解为当前字段存的是外键对象,nid相当于内存地址,

get_field是针对models中模型使用的,主要目的是拿到该字段是由谁实例化的

print(type(models.Article._meta.get_field("user")))print(type(models.Article._meta.get_field("tags")))------------------------------------------结果是:    

也就是说他拿到的是等号后面的类实例化对象

---------------------

其次参数是不一样的,getattr第一个参数是对象,而_meta.get_field是django下面特有的方法

而用getattr取对象中的双下划綫方法,就相当于执行函数拿到相应的值

 

__ str__,get_field,getattr初识
str ,当用getattr进行取值,默认返回对象内的__str __内返回值

class Tag(models.Model):    """    标签    """    nid = models.AutoField(primary_key=True)    title = models.CharField(max_length=32)  # 标签名    blog = models.ForeignKey(to="Blog", to_field="nid" ,on_delete=models.CASCADE)  # 所属博客    def __str__(self):        return self.title    class Meta:        verbose_name = "标签"        verbose_name_plural = verbose_nameobj=models.Blog.objects.filter().first()getattr(obj,field)---------------------------------结果是:     self.title对应的值,因为双下划綫一定会执行的

get_field(field _name)获取字段对应的对象,如title = models.CharField(max _length=32) ,我们获取到的是CharField实例化的对象,通过对象就可以拿到相应的参数值

title_list.append(self.model._meta.get_field(field).verbose_name)  #求字段中文名

getattr

获取==对象== object 的属性或者方法,若存在则打印出来;若不存在,则打印默认值,默认值可选。注意:如果返回的是对象的方法,那么打印的结果是方法的内存地址。如果需要运行这个方法,那么可以在后面添加括号 () 。

函数对象名字提取

def b():    passprint(b.__name__)b.short="1233456"print(b.short)--------------------------    结果是:    b    1233456

反向解析

切记第二个参数是可迭代数据,因此否则会报错

from django.urls import reverse    def get_udate_url(self,obj):        _url = reverse("%s_%s_update" % (self.app_name, self.table_name), args=[obj.pk, ])  # 反向解析        return _url

字符串标签安全布局

from django.utils.safestring import mark_safedef checkbox_button(self,obj=None,header=False):    if header:        return  mark_safe("")    return  mark_safe("")

保存当前传进来的路径,并跟新参数

参数提取与更新,运用了django内置的转换格式.

request.Get拿到的是字典形式参数   
request_params.urlencode() 把chuanjinlai的参数转化成page=7>=10

HTML中还可以执行函数

在HTML中执行函数

class Show_list(object):    def __init__(self,config,data_list):        self.config=config        self.data_list=data_list    def get_TableHead(self):        title_list = []        for field in self.config.rebulid_display_list():            if isinstance(field, str):                if field == "__str__":                    title_list.append(self.config.table_name.upper())  # 如果传显示列表就返回表名                else:                    title_list.append(self.config.model._meta.get_field(field).verbose_name)  # 求字段中文名            else:  # if callable(field)   判断是不是函数                                                                 # 函数怎么命名                var = field(self.config, header=True)                title_list.append(var)  # 求函数名        return title_list    def get_TableBody(self):        items_list = []        for obj in self.data_list:            # 某一个字段对象            item=[]            for field in self.config.rebulid_display_list():        #["title","desc",add_0]  ["__str__"]                   if not callable(field):                        if field in self.config.list_display_link:                            url = self.config.get_udate_url(obj)                            item.append(mark_safe("%s"%(url,getattr(obj,field))))                        # 求字段名                        else:                            item.append(getattr(obj,field))        # 当是多对多的关系时,这个也可以的                                                                # 在模型表当中定义了__str__,执行或者打印都返回指定数据,原来是为这里服务                   else:                       item.append(field(self.config,obj))            items_list.append(item)        return  items_list        def list_views(self, request, *args):    data_list,paging_label=self.get_paging(request)    show_list=Show_list(self,data_list)    add_url=self.add_url()    return render(request, "XXadmin/XXadmin_check.html",                  {                   "add_url":add_url,                   "paging_label":paging_label,                   "show_list":show_list                  })

html执行函数方法

{% for title in show_list.get_TableHead %}
{% endfor %}
{% for foo in show_list.get_TableBody %}
{% for item in foo %}
{% endfor %}
{% endfor %}
{
{ title }}
{
{ item }}

xadmin功能实现

批量处理方法

自定义批量方法,并在表注册的时候存放在自定义的类中,然后以列表的形式把函数存放起来

def delete_table(self,request,queryset):    #  删除数据    queryset.delete()def update_table(self,request,queryset):    #  更新数据    queryset.update()    delete_table.shortdesc="批量删除"update_table.shortdesc="批量修改"action=[delete_table,update_table]# 注意函数也是对象,可以添加描述属性,目的是为了在HTML中显示该步骤是什么操作

然后在Xadmin中调用该列表,取出相应方法,和描述,存放在一个列表当中,方便在HTML中循环显示

self.action=[{"name": i.__name__,"desc":i.shortdesc} for i in  self.config.action]

最后在HTML中显示该操作方法

image

因为是修改数据库操作,因此要用post请求,防止xss攻击

在视图处理,因为在自定义的是时候没有前端传过来的action和要批量处理的数据,因此只能够定义删除方法

def many_action(self,request,queryset):    action = request.POST.get("action", "")    action1 = getattr(self.config,action)    action1(request, queryset)            #    批量处理时在views视图中调用该方法if request.method == "POST":    condition = request.POST.getlist('item', "")    queryset = self.model.objects.filter(pk__in=condition)    show_list.many_action(request,queryset)

request.get或者request.post返回的是函数参数部分,或者是表单提交的数据

还要注意get和get_list的区别

返回全部数据    condition = request.POST.getlist('item', "")只返回列表当中的最后一个    condition = request.POST.get('item', "")

搜索功能实现

Q查询补充

主要用到了Q查询的,字符串拼接法,条件的字符串

传入条件进行查询:

q1 = Q()q1.connector = 'OR'q1.children.append(('id', 1))q1.children.append(('id', 2))q1.children.append(('id', 3))    models.Tb1.objects.filter(q1)

合并条件查询

con = Q()q1 = Q()q1.connector = 'OR'q1.children.append(('id', 1))q1.children.append(('id', 2))q1.children.append(('id', 3))q2 = Q()q2.connector = 'OR'q2.children.append(('status', '在线'))con.add(q1, 'AND')con.add(q2, 'AND')models.Tb1.objects.filter(con)

主要思路是把搜索条件拼接在相应的a标签中,等到下一次查询时,就把相应的查询条件放在相应的a标签中,这时就会带着上一次查询条件进行查询,也就是说,每一次查询都会重新渲染页面

分页代码中拼接条件,首先得用request.get求出所有参数,其是字典形式的参数,因此需要修改响应值可以通过

注意在修改数据之前需要备份,防止在下一个函数处理数据时,会用到修改后的数据

self.request_params=copy.deepcopy(request_get)            # 复制一份原有传进的的参数,不影响原有数据,当在函数下执行时

因此在修改后的数据进行修改

self.request_params["page"]=1

对函数进行序列化,转换成url路径参数的形式

{'action': ['delete_table'], 'check': ['on'], 'item': ['102', '103', '104', '105', '106', '107', '108', '109', '110', '111']}

url特有的方法

self.request_params.urlencode()action ='delete_table'&check=['on']&item=['102', '103', '104', '105', '106', '107', '108', '109', '110', '111']

最后把相应的参数拼接到a标签当中即可,完成,条件保留

紧接着就是条件拼接

def search_contition(self,request):    key_word=request.GET.get("key_word","") # key_word默认为空    self.key_word=key_word    contion = Q()    contion.connector = "or"  # 改变q条件之间的关系为   or  关系    if not self.search_list:        pass    else:        for field in self.search_list:            contion.children.append((field+"__contains",key_word))    return contioncon=search_contition(request)if con:    # 判断查询    data_list=self.model.objects.filter(con)else:    data_list=self.model.objects.all()    # 如何判断是查询还是分页,放在同一个条件中,看你有没有查询条件,没有则帅选全部数据
{'csrfmiddlewaretoken': ['cNsATE1XfZLsG3h6fwBRYLtXgFaHGA5zOAny87XGqsvdNCI2B8hQENvedrjE86bB'], 'action': ['delete_table'], 'check': ['on'], 'item': ['102', '103', '104', '105', '106', '107', '108', '109', '110', '111']}

分页中经典算法

for i in range(self.page_start, self.page_end + 1):            self.request_params["page"] = i            if i == self.current_page:                tmp = '
  • {2}
  • '.format(self.current_url,self.request_params.urlencode(), i) else: tmp = '
  • {2}
  • '.format(self.current_url,self.request_params.urlencode(),i) # 把字典转换成等式,i) l.append(tmp) # request.Get拿到的是字典形式参数
    # request_params.urlencode() 把chuanjinlai的参数转化成page=7>=10 # 加一个下一页上一页,首页,末页 if self.total_page: if self.current_page == 1 and self.total_page==1: l.insert(0,'
  • «
  • ') l.append('
  • »
  • ') elif self.current_page==1: l.insert(0, '
  • «
  • ') self.request_params["page"] = self.current_page + 1 l.append('
  • »
  • '.format(self.current_url,self.request_params.urlencode())) elif self.total_page==self.current_page: self.request_params["page"] = self.current_page - 1 l.insert(0, '
  • «
  • '.format(self.current_url,self.request_params.urlencode())) self.request_params["page"] = self.total_page l.append('
  • »
  • '.format(self.current_url,self.request_params.urlencode() )) else: self.request_params["page"] = self.current_page - 1 l.insert(0, '
  • «
  • '.format(self.current_url,self.request_params.urlencode())) self.request_params["page"] = self.current_page + 1 l.append('
  • »
  • '.format(self.current_url, self.request_params.urlencode())) self.request_params["page"] =1 l.insert(0, '
  • 首页
  • '.format(self.current_url,self.request_params.urlencode())) self.request_params["page"] =self.total_page l.append('
  • 尾页
  • '.format(self.current_url,self.request_params.urlencode())) return l

    分类功能

    通过以下方法可以拿到外键表中所有的实例化对象

    Article._meta.get_field(field_name).remote_field.model.objects.all()# 通过他可以拿到外键表所有实例化对象

    实验说明

    class A():    passa=A()print(type(a))--------------------------------------结果是:    
    # 当前文件下,A类实例化的对象 filter_list=["user","tags","category"]def get_filter_html(self): catage_list = self.config.filter_list for field in catage_list: # 拿到分类字段,即组合依据 data_list=self.config.model._meta.get_field(field).remote_field.model.objects.all() # 获取字段对象并反射获取外键表某字段的全部返回值 for obj in data_list: print(type(obj))------------------------------------------结果是:
    拿到的是类对应实例化对象
    models.Article._meta.get_field("tags").remote_field.model.objects.all()---------------------------------------结果是    
    ,
    ,
    ]>

    getattr拿到的是反射对象中__ str__定义的返回值,因为该方法获取到的是外键表所有实例化的对象,因此才会返回__ str__数据

    def __str__(self):        return self.title

    注意当有两个参数时,for循环取值,只会拿到最后一个值,需要分别用getlist取值

    print(request.GET) for k,v in request.GET.items():   print(k)   print(type(v),v)   ----------------------------------------   结果是:    
    user
    12 tags
    2

    转载于:https://www.cnblogs.com/AbnerLc/p/11203876.html

    你可能感兴趣的文章
    Solr搜索分页
    查看>>
    数据预处理-机器学习
    查看>>
    CSS基础学习-4.CSS属性_背景、颜色、边框
    查看>>
    SOFTWARE
    查看>>
    MySQL卸载重安装异常解决
    查看>>
    学习 JavaScript (六)核心概念:函数
    查看>>
    CentOS7下源码安装mysql5.6
    查看>>
    Vue表单和组件
    查看>>
    PHP多态的理解
    查看>>
    MySQL的学习之旅(2)
    查看>>
    JavaScript 随意整理
    查看>>
    sometofstuding
    查看>>
    servlet中请求转发(forword)与重定向(sendredirect)的区别
    查看>>
    Python_python单元测试
    查看>>
    如何生成自签名SAN/UCC证书
    查看>>
    Linux命令grep
    查看>>
    Angular4 + NG-ZORRO 开发 后台系统 用户管理
    查看>>
    django文件上传
    查看>>
    09JavaScript中面向对象!
    查看>>
    JavaScript this运用
    查看>>