目录

深浅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("<a href='%s'>编辑</a>" % 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: <class 'int'>
title: <class 'str'>
user: <class 'app01.models.UserInfo'>

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

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

print(type(models.Article._meta.get_field("user")))

print(type(models.Article._meta.get_field("tags")))
------------------------------------------
结果是:
<class 'django.db.models.fields.related.ForeignKey'> <class 'django.db.models.fields.related.ManyToManyField'>

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

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

其次参数是不一样的,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_name obj=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():
pass
print(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_safe
def checkbox_button(self,obj=None,header=False):
if header:
return mark_safe("<label><input type='checkbox' name='check' class='control_all'></label>")
return mark_safe("<label><input type='checkbox' class='item_choice'></label>")

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

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

request.Get拿到的是字典形式参数   <QueryDict: {'page': ['7'], 'gt': ['10']}>
request_params.urlencode() 把chuanjinlai的参数转化成page=7&gt=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("<a href='%s'>%s</a>"%(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执行函数方法

<table class="table">
<thead>
<tr> {% for title in show_list.get_TableHead %}
<th>{{ title }}</th>
{% endfor %} </tr>
</thead>
<tbody>
{% for foo in show_list.get_TableBody %}
<!-- 拿到的是一个列表 -->
<tr> {% for item in foo %}
<td>{{ item }}</td>
{% endfor %} </tr>
{% endfor %}
</tbody>
</table>

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中显示该操作方法

   <select name="action" id="action">
<option value="">------------</option> {% for i in show_list.action %}
<option value="{{ i.name }}">{{ i.desc }}</option>
{% endfor %}
</select>

因为是修改数据库操作,因此要用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 contion con=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 = '<li class="active"><a href="{0}?page={1}">{2}</a></li>'.format(self.current_url,self.request_params.urlencode(), i)
else:
tmp = '<li><a href="{0}?{1}">{2}</a></li>'.format(self.current_url,self.request_params.urlencode(),i) # 把字典转换成等式,i)
l.append(tmp)
# request.Get拿到的是字典形式参数 <QueryDict: {'page': ['7'], 'gt': ['10']}>
# request_params.urlencode() 把chuanjinlai的参数转化成page=7&gt=10 # 加一个下一页上一页,首页,末页
if self.total_page:
if self.current_page == 1 and self.total_page==1:
l.insert(0,'<li class="disabled" ><a href="#">«</a></li>')
l.append('<li class="disabled"><a href="#">»</a></li>')
elif self.current_page==1:
l.insert(0, '<li class="disabled" ><a href="#">«</a></li>')
self.request_params["page"] = self.current_page + 1
l.append('<li><a href="{}?{}">»</a></li>'.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, '<li ><a href="{}?{}">«</a></li>'.format(self.current_url,self.request_params.urlencode()))
self.request_params["page"] = self.total_page
l.append('<li class="disabled"><a href="{0}?{1}">»</a></li>'.format(self.current_url,self.request_params.urlencode() ))
else:
self.request_params["page"] = self.current_page - 1
l.insert(0, '<li ><a href="{0}?{1}">«</a></li>'.format(self.current_url,self.request_params.urlencode())) self.request_params["page"] = self.current_page + 1
l.append('<li><a href="{0}?{1}">»</a></li>'.format(self.current_url, self.request_params.urlencode())) self.request_params["page"] =1
l.insert(0, '<li ><a href="{}?{}">首页</a></li>'.format(self.current_url,self.request_params.urlencode()))
self.request_params["page"] =self.total_page
l.append('<li ><a href="{}?{}">尾页</a></li>'.format(self.current_url,self.request_params.urlencode()))
return l

分类功能

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

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

实验说明

class A():
pass
a=A()
print(type(a))
--------------------------------------
结果是:
<class '__main__.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))
------------------------------------------
结果是:
<class 'app01.models.UserInfo'>
<class 'app01.models.UserInfo'>
<class 'app01.models.UserInfo'>
<class 'app01.models.UserInfo'>
<class 'app01.models.UserInfo'>
<class 'app01.models.Tag'>
<class 'app01.models.Tag'>
<class 'app01.models.Tag'>
<class 'app01.models.Category'>
<class 'app01.models.Category'>
<class 'app01.models.Category'>
<class 'app01.models.Category'>
<class 'app01.models.Category'>
拿到的是类对应实例化对象
models.Article._meta.get_field("tags").remote_field.model.objects.all()

---------------------------------------
结果是
<QuerySet [<Tag: 游戏>, <Tag: 生活>, <Tag: 情感>]>

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) ----------------------------------------
结果是:
<QueryDict: {'user': ['12'], 'tags': ['1', '2']}>
user
<class 'str'> 12
tags
<class 'str'> 2

Xadmin查询的更多相关文章

  1. django xadmin多对多字段过滤(含filter的反向查询)

    要实现的功能: 继昨天实现拓展User模型使其得到其上级用户,今天要实现某些模型与用户多对多字段过滤功能. 功能描述:以用户指派功能为例,当前用户将文件指派给多个下级,修改前 程序会将所有用户都显示出 ...

  2. 关于django xadmin的学习改造(菜单名称,更改默认前缀数据库)

    路径xadmin-master\demo_app\app\models.py class c(models.Model): ip_address = models.CharField(max_leng ...

  3. Django+xadmin打造在线教育平台(二)

    三.xadmin后台管理 3.1.xadmin的安装 django2.0的安装(源码安装方式): https://github.com/sshwsfc/xadmin/tree/django2 把zip ...

  4. Django+xadmin打造在线教育平台(三)

    五.完成注册.找回密码和激活验证码功能 5.1.用户注册 register.html拷贝到templates目录 (1)users/views.py class RegisterView(View): ...

  5. Django+xadmin打造在线教育平台(四)

    七.授课机构功能 7.1.模板继承 (1)创建母板 把org-list.html拷贝到templates目录下,新建base.html,剪切org-list.html内容到里面 再修改一下静态文件的地 ...

  6. Django+xadmin打造在线教育平台(六)

    九.课程章节信息 9.1.模板和urls 拷贝course-comments.html 和 course-video.html放入 templates目录下 先改course-video.html,同 ...

  7. Django之Xadmin

    零.预备知识 单例对象 方式一:__new__方法 方式二:模块导入,只要在引入的文件中实例了这个对象,不管引道哪里,这个对象都指向同一个内存空间 class My_singleton(object) ...

  8. Django+xadmin的安装与配置

    已安装python3.6.5rcl 已安装django-1.10.8(后续有错) 一.安装xadmin 1.下载xadmin,下载地址:https://github.com/sshwsfc/xadmi ...

  9. 七、xadmin 编辑界面实现二级联动

    很多时候,我们会遇到这种需求,通过一个select框中选择的值,去动态的加载另一个下拉框中的内容 对于前端的同学来讲,这个本应该是一个很简单的需求,获取第一个下拉框的值然后通过ajax去动态加载即可. ...

随机推荐

  1. 用PhpStrom线上连接修改linux服务器上代码配置

    为了进一步提高自己的技能水平,不久前入手了一台服务器,不贵,一年也就不到两百,因为自己对于linux机器比较生疏,命令用的有点抠脚.老需要查阅处理. 于是我选择用PhpStrom直接连接线上服务器,通 ...

  2. css3-旋转的太极图

    123 body { background-color: #aaa; } .div { width: 400px; height: 400px; border-radius: 50%; border: ...

  3. Nginx安装及详解

    Nginx简介: Nginx(发音engine x)专为性能优化而开发的开源软件,是HTTP.反向代理.邮件代理.TCP/UDP协议代理软件,由俄罗斯的作者Igor Sysoev开发,其最知名的优点是 ...

  4. 线上问题排查神器 Arthas

    线上问题排查神器 Arthas 之前介绍过 BTrace,线上问题排查神器 BTrace 的使用,也说它是线上问题排查神器.都是神器,但今天这个也很厉害,是不是更厉害不好说,但是使用起来非常简单.如果 ...

  5. SqlServer2014怎样还原数据库

    场景 在SqlServer2014企业版上怎样进行数据库的还原,首先你得有一个其他数据 的备份文件. 实现 打开cmd,输入sql,打开SqlServer 2014 Management Studio ...

  6. Winform中自定义xml配置文件后对节点进行读取与写入

    场景 Winform中自定义xml配置文件,并配置获取文件路径: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100522648 ...

  7. rabbitmq+haproxy+keepalived高可用集群环境搭建

    1.先安装centos扩展源: # yum -y install epel-release 2.安装erlang运行环境以及rabbitmq # yum install erlang ... # yu ...

  8. 大数据平台搭建 - cdh5.11.1 - hbase集群搭建

    一.简介 HBase是一种构建在HDFS之上的分布式.面向列的存储系统.在需要实时读写.随机访问超大规模数据集时,可以使用HBase. 尽管已经有许多数据存储和访问的策略和实现方法,但事实上大多数解决 ...

  9. Sticks(剪枝+BFS)

    Problem Description George took sticks of the same length and cut them randomly until all parts beca ...

  10. 腾讯云和阿里云部署web 项目tomcat 日志 中文变成问号

    在部署项目到云上的时候,遇到了tomcat logs 日志中文变问号的问题,今天终于得到解决了 这是中文变成问号的的截图 打开到tomcat bin 目录的文件夹 找到catalina.sh  文件 ...