仿照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. RN-ios模拟器上调出中文输入法

    react-native 项目:在ios模拟器上需要拼写汉字,步骤是, 1.在模拟器的设置-通用-语言与地区-iphone语言设置为:简体中文 2.模拟器的 Hardware-Keyboard-勾选下 ...

  2. css篇-less,scss 用calc问题

    在less或者scss中 calc(100% -4rem) 等带单位混合运算会被less解析忽略单位,全部按照百分比计算,此例中的计算被less编译成calc(96%), 解决办法: width:(& ...

  3. Object类(API文档)

    java.lang Class Object java.lang.Object public class Object Class Object is the root of the class hi ...

  4. vue axios get请求参数为json对象 而非字符串形式

    axios get请求方式 传递给后台的参数都是字符串下形式,无法传递json对象 或数组对象等    post请求方式则可以实现,   但若后台接口要求必须用get方式传递对象给后台,需要装插件,实 ...

  5. clone git 项目到 非空目录

    如果我们往一个非空的目录下 clone git 项目,就会提示错误信息: fatal: destination path '.' already exists and is not an empty ...

  6. awesome vue

    https://blog.csdn.net/caijunfen/article/details/78216868

  7. spark sql的agg函数,作用:在整体DataFrame不分组聚合

    .agg(expers:column*) 返回dataframe类型 ,同数学计算求值 df.agg(max("age"), avg("salary")) df ...

  8. SaltStack 数据系统 Grains Pillar

    grains 先来一个很好用的命令 # salt '*' grains.items \\基本上输出了所有你想要的信息 192.168.100.138: ---------- SSDs: biosrel ...

  9. Python3.6下使用会话session保持登陆状态

    本次工具主要利用python easygui模块的inputbox让用户首次输入登陆信息,作为网站requests-post请求的data字段,观察XHR(异步加载)的数据包,构造post请求,利用r ...

  10. 超实用教程,教你用墨刀做出小红书app原型

    一个新手怎么用1小时快速学会APP原型设计? 1小时很短,这意味着学习时必须把握APP原型设计中的重点.难点,而非面面俱到. 要在短时间内理解.掌握一个工具的使用,最有效的方式莫过于临摹: 看实例视频 ...