目录

深浅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. Intellij IDEA在maven项目中添加外部Jar包运行

    一. 问题概述 我们知道Intellij IDEA是非常好用的Java语言开发的集成环境.提供了非常多实用的功能,包括了智能代码助手.代码自动提示.代码重构.各种插件等,当然也集成了maven 正常情 ...

  2. Java,哈希码以及equals和==的区别

    从开始学习Java,哈希码以及equals和==的区别就一直困扰着我. 要想明白equals和==的区别首先应该了解什么是哈希码,因为在jdk的类库中不管是object实现的equals()方法还是S ...

  3. 上传文件的C#代码

    1 <%@ WebHandler Language="C#" Class="UpLoadFile" %> 2 3 using System; 4 u ...

  4. Python(Head First)学习笔记:三

    3 文件与异常:调试.处理错误.迭代.改进.完善  处理错误:利用Python的异常处理机制来处理异常情况.  程序外部的数据:大多程序基本模型:首先输入数据,进行处理,然后存储.显示.打印或传输. ...

  5. Salesforce学习之路-admin篇

    Salesforce是一款非常强大的CRM(Customer Relationship Management)系统,国外企业使用十分频繁,而国内目前仅有几家在使用(当然,国内外企使用的依旧较多),因此 ...

  6. 自定义JDBC工具类

    因为数据库的连接代码都是固定的,为了将减少重复的代码的书写,可以将这些代码封装为一个工具类,获取数据库的连接对象. import java.sql.Connection; import java.sq ...

  7. SSO-CAS实现单点登录服务端

    目录 CAS-SSO 一.单点登录-CAS 二.下载搭建CAS 1. 下载 CAS 5.3 2. 导入IDEA 3. 打包war 3. war包部署到Tomcat 4. 启动Tomcat,访问 htt ...

  8. jsp作用域总结

    我们在定义每一个变量,每一个属性的时候,都会考虑这个变量.属性的作用范围,也就是作用域. JSP的四大作用域 作用域对象 作用域范围 page 只在当前页面有效 request 一次请求的生命周期内有 ...

  9. Day 22 进程管理2之系统的平均负载

    1.管理进程状态 当程序运行为进程后,如果希望停止进程,怎么办呢? 那么此时我们可以使用linux的kill命令对进程发送关闭信号.当然除了kill.还有killall,pkill 1.使用kill ...

  10. Flink 编程接口

    欢迎来 kk大数据,今天分享的是 Flink 提供了哪些编程接口可以给我们开发. 一.数据集类型 现实世界中,所有的数据都是以流式的形态产生的,不管是哪里产生的数据,在产生的过程中都是一条条地生成,最 ...