Xadmin查询
目录
深浅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>=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>=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查询的更多相关文章
- django xadmin多对多字段过滤(含filter的反向查询)
要实现的功能: 继昨天实现拓展User模型使其得到其上级用户,今天要实现某些模型与用户多对多字段过滤功能. 功能描述:以用户指派功能为例,当前用户将文件指派给多个下级,修改前 程序会将所有用户都显示出 ...
- 关于django xadmin的学习改造(菜单名称,更改默认前缀数据库)
路径xadmin-master\demo_app\app\models.py class c(models.Model): ip_address = models.CharField(max_leng ...
- Django+xadmin打造在线教育平台(二)
三.xadmin后台管理 3.1.xadmin的安装 django2.0的安装(源码安装方式): https://github.com/sshwsfc/xadmin/tree/django2 把zip ...
- Django+xadmin打造在线教育平台(三)
五.完成注册.找回密码和激活验证码功能 5.1.用户注册 register.html拷贝到templates目录 (1)users/views.py class RegisterView(View): ...
- Django+xadmin打造在线教育平台(四)
七.授课机构功能 7.1.模板继承 (1)创建母板 把org-list.html拷贝到templates目录下,新建base.html,剪切org-list.html内容到里面 再修改一下静态文件的地 ...
- Django+xadmin打造在线教育平台(六)
九.课程章节信息 9.1.模板和urls 拷贝course-comments.html 和 course-video.html放入 templates目录下 先改course-video.html,同 ...
- Django之Xadmin
零.预备知识 单例对象 方式一:__new__方法 方式二:模块导入,只要在引入的文件中实例了这个对象,不管引道哪里,这个对象都指向同一个内存空间 class My_singleton(object) ...
- Django+xadmin的安装与配置
已安装python3.6.5rcl 已安装django-1.10.8(后续有错) 一.安装xadmin 1.下载xadmin,下载地址:https://github.com/sshwsfc/xadmi ...
- 七、xadmin 编辑界面实现二级联动
很多时候,我们会遇到这种需求,通过一个select框中选择的值,去动态的加载另一个下拉框中的内容 对于前端的同学来讲,这个本应该是一个很简单的需求,获取第一个下拉框的值然后通过ajax去动态加载即可. ...
随机推荐
- 【Offer】[45]【把数组排成最小的数】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如,输入数组{3,32,321},则打印出 ...
- java对象与json字符串的互相转换
java对象与json字符串的互相转换 1.采用 net.sf.json.JSONObject maven依赖包: <dependency> <groupId>net.sf.j ...
- SpringMVC的工作原理图
SpringMVC的工作原理图: SpringMVC流程 1. 用户发送请求至前端控制器DispatcherServlet. 2. DispatcherServlet收到请求调用HandlerMa ...
- 如何使用Java访问双向认证的Https资源
本文的相关源码位于 https://github.com/dreamingodd/CA-generation-demo 0.Nginx配置Https双向认证 首先配置Https双向认证的服务器资源. ...
- python SSTI利用
原理python的SSTI不仅可以向网页插入一些XSS代码,而且还可以获取一些变量和函数信息,尤其是secret_key,如果获取到则可以对flask框架的session可以进行伪造.对于tornad ...
- django学之路01--环境安装和pycharm运行django项目
1. 环境安装 1).virtualenv安装 C:\Users\Administrator>pip install virtualenv Collecting virtualenv Using ...
- dart 大文件读取
dart 中不可避免会出现文件读取的情况, 甚至是很大的文件, 比如 200M 的文件 如果一次性读入内存,虽然也行得通, 但是如果在 flutter 中开启个 200M 大小的字节数组, 一不小心可 ...
- TestNG(八) 类分组测试
package com.course.testng.groups; import org.testng.annotations.Test; @Test(groups = "stu" ...
- Phpstudy被暴存在隐藏后门-检查方法
Phpstudy被暴存在隐藏后门-检查方法 一.事件背景 Phpstudy软件是国内的一款免费的PHP调试环境的程序集成包,通过集成Apache.PHP.MySQL.phpMyAdmin.ZendOp ...
- Java 截取字符串中指定数据及之后数据
String resCallBackJson="12556{1{{{456858585{"; resCallBackJson = resCallBackJson.su ...