仿照admin的stark自定义组件的功能实现:其中最主要的就是增删改查的实现

1、查:首先页面中显示表头和数据,都是动态的,而不是写死的。

(1) 先看表头和表单数据:这个是查看的视图函数,但是为了使视图函数里边的代码简洁,在默认配置类的外部定义一个展示类,

因为在展示页面上会展示我们数据库中的数据,搜索框,过滤框,等。所以专门定义一个展示类。

# 查看视图函数,将此里边的函数封装成一个函数
def listview(self, request):
# print(self) # 当前访问模型表的配置类对象
# print(self.model) # 当前访问模型表
# print(self.list_display)
if request.method == "POST":
# 获取到我们选中的id,即对象
pk_list = request.POST.getlist("pk_list")
# 看id是否在pk_list中
queryset = self.model.objects.filter(pk__in=pk_list)
# 或取到这个名字即函数名
action = request.POST.get("action")
# 因为获取的是字符串,所以要用反射,self表示配置类对象
# 判断是否存在
if action:
action=getattr(self,action)
action(request,queryset)
data_list = self.model.objects.all()
# 在这个页面上增加一个增加数据的按钮,跳转到那个路径
add_url = self.get_add_url()
# 获取搜索条件对象
search_condition = self.get_search_condition(request)
# 获取filter的condition
filter_condition = self.get_filter_condition(request) # 数据过滤展示
data_list = data_list.filter(search_condition).filter(filter_condition)
# 分页展示
showlist = ShowList(self, data_list, request)
# filter,调用
showlist.get_list_filter() return render(request, "list_view.html", locals())

展示类:

class ShowList(object):
# 初始化
def __init__(self, config_obj, data_list, request):
self.config_obj = config_obj # 当前查看表的配置类对象
self.data_list = data_list
self.request = request # 分页
self.pagination = MyPage(request.GET.get("page", 1),self.data_list.count(),request,per_page_data=3)
self.page_queryset = self.data_list[self.pagination.start:self.pagination.end] # actions操作
def get_new_actions(self):
temp = []
temp.extend(self.config_obj.actions)
temp.append(self.config_obj.patch_delete)
new_actions = []
print(self.config_obj.actions) # [patch_init,patch_delete]这个对象
print(temp)
for func in temp:
new_actions.append({
"text":func.desc,
"name":func.__name__
})
# print(new_actions)
# [{'text': '价格初始化', 'name': 'patch_init'}, {'text': '批量删除', 'name': 'patch_delete'},
return new_actions # 表头函数
def get_headers(self):
# 构建表头
# 想要的形式是这种形式header_list=["书籍名称","价格"]
header_list = []
for field_or_func in self.config_obj.new_list_display(): # 依然循环["title","price","publish",edit]
# 如果是函数的话这样
if callable(field_or_func):
# 如果是函数
val = field_or_func(self.config_obj, is_header=True)
else:
# # 如果只是单纯的字符串字段
# 如果这个字段是__str__
if field_or_func == "__str__":
val = self.config_obj.model._meta.model_name.upper()
print(val)
else:
# 获取到的是字段里边的verbose_name,如果没这个就是默认的表明
field_obj = self.config_obj.model._meta.get_field(field_or_func)
val = field_obj.verbose_name
header_list.append(val)
return header_list # 表单数据部分
def get_body(self):
# 构建数据表单部分
new_data_list = [] # 先创建一个外层列表,在这个列表里边放小列表
for obj in self.page_queryset: # 循环 这个对应的列表,Queryset[book1,book2]
temp = [] # 小列表
for field_or_func in self.config_obj.new_list_display():
# 循环的就是你display中的东西,不仅有字段相对应的字符串,还可能有自定义的函数["title","price","publish",edit]
# 故要做判断,callable是判断是否是函数,
if callable(field_or_func):
# 如果是函数,则执行这个函数
val = field_or_func(self.config_obj, obj)
else:
# 如果是字符串,
# 如果是多对多字段,先导入一个from django.db.models.fields.related import ManyToManyField
# 这个是获取出来字段,
try:
field_obj = self.config_obj.model._meta.get_field(field_or_func)
print(field_obj)
# app01.Book.title
# app01.Book.price
# app01.Book.publish
# app01.Book.authors
if isinstance(field_obj, ManyToManyField):
# 然后判断哪个字段是多对多字段,isinstance就是判断是否是多对多字段
# 如果是就要用.all()全部获取出来,
rel_data_list = getattr(obj, field_or_func).all()
print(rel_data_list)
# 获取出来每本书对应的作者这个对象
# <QuerySet [<Author: 沈巍>, <Author: 蓝忘机>]>
l = [str(item) for item in rel_data_list]
# 经过for循环,并且转成字符串,用|隔开
val = "|".join(l)
# 如果这个字段在links里边,获取一下路径,生成a标签
if field_or_func in self.config_obj.list_display_links:
_url = self.config_obj.get_change_url(obj)
val = mark_safe("<a href='%s'>%s</a>"%(_url, val))
else:
# 如果不是多对多字段,就直接获取就行
val = getattr(obj, field_or_func) # 反射
# 如果这个字段在links里边,获取一下路径,生成a标签
if field_or_func in self.config_obj.list_display_links:
_url = self.config_obj.get_change_url(obj)
val = mark_safe("<a href='%s'>%s</a>"%(_url, val))
except Exception as e:
val = getattr(obj, field_or_func) # 反射
# 都添加到小列表中
temp.append(val)
# 添加到大列表中
new_data_list.append(temp)
return new_data_list # filter操作,可以写在listview里边,但是为了listview里边代码清晰,所以写在这个类里边
def get_list_filter(self):
# 这个弄成字典,是为了前端方便获取,而且方便存值
list_filter_links = {}
# for 循环这个字段列表 ['publish', 'authors']
for field in self.config_obj.list_filter:
# 因为这个要保存之前的路径
parmas = copy.deepcopy(self.request.GET)
# 获取当前字段的id
current_pk = parmas.get(field, 0)
# 获取这个字段的对象
field_obj = self.config_obj.model._meta.get_field(field)
# 固定语法,得到关联字段的那张表
rel_model = field_obj.rel.to
# 得到这个表之后,直接获取这个表的所有数据
rel_model_queryset = rel_model.objects.all()
# < QuerySet[ < Publish: 镇魂出版社 >, < Publish: 忘羡出版社 >, < Publish: 北京出版社 >, < Publish: 晋江出版社 >] >
# print(rel_model_queryset)
# 得到这个出版社后,在for循环
temp = []
for obj in rel_model_queryset:
# 字典,键是字段,值是id值
parmas[field] = obj.pk
if obj.pk == int(current_pk):
# 如果字典中的id值和当前获取的一致,颜色变色
link = "<a class='active' href='?%s'>%s</a>" % (parmas.urlencode(), str(obj))
else:
# 其他颜色不变化,
link = "<a href='?%s'>%s</a>" % (parmas.urlencode(), str(obj))
temp.append(link)
list_filter_links[field] = temp
return list_filter_links

如果是自定义列的话,应该将list_display做一下调整

# 定义一个新的列表,既存放字段,有存放edit,delete,checkbox
def new_list_display(self):
temp = []
# 把我原来的list_display数据添加进去
temp.extend(self.list_display)
# 把checkbox插入在第一位
temp.insert(0, ModelStark.checkbox)
# 继续往后添加edit字符串
# 我们因为增加了一个link属性,所以就在这里判断一下,
# 如果有links这个属性,我们就不添加增加这个属性了,如果没有的话,我们增加
if not self.list_display_links:
temp.append(ModelStark.edit)
# 继续往后添加删除字符串
temp.append(ModelStark.delete)
return temp
# 默认操作函数
def edit(self, obj=None, is_header=False):
if is_header:
return "操作"
return mark_safe("<a href='%s' class='btn btn-warning btn-sm'>编辑</a>" % self.get_change_url(obj)) def delete(self, obj=None, is_header=False):
if is_header:
return "删除"
return mark_safe("<a href='%s' class='btn btn-danger btn-sm'>删除</a>" % self.get_delete_url(obj)) def checkbox(self, obj=None, is_header=False):
if is_header:
return "选择"
return mark_safe("<input type='checkbox' name='pk_list' value=%s>" % obj.pk)

(2)表单表头部分应该注意的有:

1)在表单数据显示部分有多对多字段的,原生admin是没有做操作的,因为原生的没有规定以什么分割,但是在这里我们进行了操作,是以|分割的,所以可以显示。

2)自定义列的时候,首先判断是普通字段,还是我们自定义的函数,如果是普通字段,因为得到的是字符串,所以用反射就可以实现

仿照admin的stark自定义组件的功能实现的更多相关文章

  1. admin源码解析以及仿照admin设计stark组件

    ---恢复内容开始--- admin源码解析 一 启动:每个APP下的apps.py文件中. 首先执行每个APP下的admin.py 文件. def autodiscover(): autodisco ...

  2. 仿照admin实现一个自定义的增删改查的组件

    1.首先,创建三个项目,app01,app02,stark,在settings里边记得配置.然后举例:在app01的model里边写表,用的db.sqlite3,所以数据库不用再settings里边配 ...

  3. 仿照admin写一个startk组件

    settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.conten ...

  4. day84-仿照admin实现一个自定义的增删改查组件

    一.admin的使用 app01的admin.py文件: class BookConfig(admin.ModelAdmin): list_display=[] list_display_links= ...

  5. Django-CRM项目学习(二)-模仿admin实现stark

    开始今日份整理 1.stark模块基本操作 1.1 stark模块的启动 保证django自动的加载每一个app下的stark.py文件 创建django项目,创建stark项目,start app ...

  6. Android开发——构建自定义组件

    Android中,你的应用程序程序与View类组件有着一种固定的联系,例如按钮(Button). 文本框(TextView), 可编辑文本框(EditText), 列表框(ListView), 复选框 ...

  7. 微信小程序入坑之自定义组件

    前言 最近接触微信小程序,再次之前公司用的前端框架是vue ,然后对比发现,开发小程序是各种限制,对于开发者非常不友好.各种槽点太多,完全吐槽不过来,所以在此不多说,打算下次专门写一篇文章吐槽一下.本 ...

  8. 让Angular自定义组件支持form表单验证

    Angular提供了一套非常强大的表单验证库(vue和react都需要第三方库的支持),可以非常方便简单实现web应用程序中的表单验证功能.但是如何让我们自定义的组件也支持验证呢? 我遇到一个需求是封 ...

  9. 10.15仿admin开发stark组件(一)

    2018-10-15 12:28:50 越努力,越幸运!永远不要高估自己! 低调做人,高调做事! 明天开stark项目!! admin 参考连接: http://www.cnblogs.com/yua ...

随机推荐

  1. TZOJ 5640: 数据结构实验:仓库管理

    描述 某百货公司仓库中有一批电视机,按其价格严格从低到高的次序,以链表(链表含头结点)的形式存储于计算机中,链表的每个结点表示同样价格的电视机台数.现在又有m台价格为x元的电视机准备入库,请将其加入到 ...

  2. caffe 测试时间报错 Aborted at unix time

    今天测试时间报错,具体如下图: 在网上查了一下,大概的原因是由于程序中使用了随机函数造成的,后来检查了一下prototxt中有可能含有随机数的地方,去掉之后就可以了,包括shuffle:true,以及 ...

  3. python中由于中文路径引起的os.path.isfile(imgpath) == False问题

    昨天在用python脚本处理文件的时候,遇到了题述问题,明明文件时存在的,但是在用os.path.isfile(imgpath) == False进行判断的时候总是成立,在一开始以为是正反斜杠wind ...

  4. abp中linq的应用

    private IQueryable<MembershipEntity> SelectOrScrrenMember(GetMemberInput input) { string[] use ...

  5. seller vue 编写接口请求【mock数据】

    [build]-[webpack.dev.conf.js] 或 [build]-[dev-server.js] 在webpack.dev.conf.js中的写法 var appData = requi ...

  6. HBase 数据迁移方案介绍 (转载)

    原文地址:https://www.cnblogs.com/ballwql/p/hbase_data_transfer.html 一.前言 HBase数据迁移是很常见的操作,目前业界主要的迁移方式主要分 ...

  7. 调用run与调用start的区别

    调用start的结果 package TestException; public class test1 { public static void main(String[] args) { // 3 ...

  8. linux中 /dev/null命令

    /dev/null :代表空设备文件 >  :代表重定向到哪里,例如:echo "123" > /home/123.txt1  :表示stdout标准输出,系统默认值是 ...

  9. DLNg-CNN第一周

    1.边缘检测示例 *表示卷积操作,标准表示.使用3*3的过滤器对其进行卷积,将3*3的覆盖在左侧上,并将运算结果相加:第二步将窗口向右移动一个单位,进行计算...横向之后再将窗格下移一个,进行循环.. ...

  10. np.Linear algebra学习

    转自:https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.linalg.html 1.分解 //其中我觉得可以的就是svd奇异值分解吧 ...