之前主要介绍了前端页面list_fiter功能的显示,但是list_display功能的展示并没有过多介绍,这里介绍一下是如何实现的。

可以看到凡是蓝线圈起来的都是通过字段名反射一个个取出来的,红线的是通过函数来构造的,这也就说明,list_display中单是字段名是不够的,还需要加入一些数据库中没有的东西。这里可以加入字段以及构建的函数。

    list_display = [BaseStark.display_checkbox,'id','name','contact','status','source','referral_from','product','consultant','consultant_date',display_follow,display_order]

那么怎么对它进行处理呢?

表头处理:

    def header_list(self,request,*args,**kwargs):
list_display = self.get_list_display()
if list_display:
for field in list_display:
if isinstance(field, FunctionType):
header_name = field(self, row=None, header_body=False, *args, **kwargs) # 加后面的编辑框
else:
header_name = self.model_class._meta.get_field(field).verbose_name # 获取对应字段的verbose_name
yield header_name
else:
yield self.model_class._meta.model_name # 如果list_display中没有值显示表名

表内容处理:

    def body_list(self,request,queryset,*args,**kwargs):
list_display = self.get_list_display()
for row in queryset:
row_list = [] # 注意必须放在这个循环下面
if not list_display: # list_display中没有值
row_list.append(row)
yield row_list
continue
for field_or_func in list_display: # list_display中有值
if isinstance(field_or_func, FunctionType):
val = field_or_func(self, row=row, header_body=True, *args, **kwargs)
elif field_or_func in self.list_editable:
val = self.render_editable_value(row,field_or_func)
else:
field_obj = self.model_class._meta.get_field(field_or_func) # 获取字段对象
if field_obj.choices:
val = getattr(row, "get_%s_display" % field_or_func)()
elif isinstance(field_obj, ManyToManyField):
queryset = getattr(row, field_or_func).all() # ManyToManyField反射需要加all()
val_list = []
for obj in queryset:
val_list.append(str(obj))
val = '、'.join(val_list)
else:
val = getattr(row, field_or_func) # ForeignKey字段反射,ManyToManyField会出现问题
if not val:
val = ''
row_list.append(val)
yield row_list

在这里对list_display中的字段进行了判断,普通字段、Foreignkey、ManyToMany、函数分别做不同的处理。另外在循环list_display的过程中引入list_editable的功能,那么它又是怎么完成的呢?

其实就是将ForeignKey以及choice类型的字段变成select标签,每一个option的value值就是它们自身的id,普通字段就给它变成input框就可以了。

  def render_editable_value(self,row,field_or_func):
field_obj = self.model_class._meta.get_field(field_or_func) # 获取字段对象
if hasattr(row,field_or_func):
if field_obj.get_internal_type() == "ForeignKey":
field_val=getattr(row,"%s_id"%(field_obj.name))
else:
field_val=getattr(row,field_or_func)
else:
field_val=''
if not field_obj.choices and field_obj.get_internal_type() != "ForeignKey" :
if field_obj.get_internal_type() == "DateTimeField":
val = '''<input data-tag='editable' class='form-control' type='text' name='%s' value='%s' date_time='datetimepicker'>''' % (field_obj.name, getattr(row, field_obj.name) or '')
else:
val = '''<input data-tag='editable' class='form-control' type='text' name='%s' value='%s' >''' %(field_obj.name,getattr(row,field_obj.name) or '')
else:
val = '''<select data-tag='editable' class='form-control' name='%s' >''' % field_obj.name
for option in field_obj.get_choices():
if option[0] == field_val:
selected_attr = "selected"
else:
selected_attr = ''
val += '''<option value='%s' %s >%s</option>'''% (option[0],selected_attr,option[1])
return mark_safe(val)

这里有一个注意的地方,字段对象如果是choice或者foreignker类型都可以使用field_obj.get_choice(),取到的就是一个个元组组成的列表,前台通过list_editable修改完成后通过ajax进行数据发送。只发送那些改动过的数据。

    <table class="table table-hover table-bordered table_content">
<thead >
<tr>
{% for row in cl.header_list %}
<th class="table_content">{{ row }}</th>
{% endfor %}
</tr>
</thead>
<tbody id="model_table_data">
{% for row_list in cl.body_list %}
<tr>
{% for val in row_list %}
<td>{{ val }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody> </table>
function SendData() {
$('#submit').click(function () { var $action_val=$('#action').val();
var form_data = [{"action":$action_val}];
$("#model_table_data tr").each(function () {
var obj_id = $(this).children().first().find("input").val();
if (obj_id){
var row_data = {};
$(this).find("[data-tag='editable']").each(function () {
var val=$(this).val();
row_data[$(this).attr("name")] = $(this).val();
});//end find each
row_data['id'] = obj_id; form_data.push(row_data); } });//end each {#alert(JSON.stringify(form_data));#}
$.ajax({
headers:{'X-CSRFToken':$.cookie('csrftoken')},
type:'POST',
dataType:"JSON",
contentType:"application/json",
data:JSON.stringify(form_data),
success:function (arg) {
} }) }) }

这样就将需要更改的数据发送到后台了,但是是否注意,我发送ajax数据时,另外还发送了一个action的数据,这又是干什么呢?实际上在页面上我有action_list这么一个功能,在这里,将action_list选项的功能变成既可以发送form表单数据,也可以进行ajax发送,然后在后台根据发送过来的函数名称进行反射处理即可。

   {% if cl.action_list %}
<div class="form-group" style="padding: 5px 0">
<select id="action" name="action" class="form-control" style="min-width: 200px;">
<option value="">请选择相应的功能</option>
{% for item in cl.action_list %}
<option value="{{ item.name }}">{{ item.attr_dict.text }}</option>
</select>
{% if item.attr_dict.id %}
<input type="button" value="执行" id="{{ item.attr_dict.id }}" class="btn btn-primary">
{% else %}
<input type="submit" value="执行" class="btn btn-primary">
{% endif %}
{% endfor %}
</div>
{% endif %}

后台处理list_editable功能的函数

    def changelist_view(self, request,*args,**kwargs):
"""
处理显示数据的页面
:param request:
:return:
""" if request.method == 'POST':
editable_data=str(request.body,encoding='utf-8')
if editable_data:
editable_data=json.loads(editable_data)
action_name=editable_data[0].get('action') #ajax请求 action_name = request.POST.get('action') or action_name # 普通form表单请求
if action_name:
if action_name not in self.get_action_dict(): # 防止前端客户刻意修改代码,进行验证
return HttpResponse('非法请求!')
response = getattr(self, action_name)(request,*args,**kwargs) # 反射执行函数 action_name就是函数名称
if response:
return response # 返回什么结果就是什么

执行反射的函数

def muti_editable_save(self, request,*args,**kwargs):
"""
ajax实现list_editble保存,通过判断是否有id属性 muti_editable_save.attr_dict = {'text':'批量保存','id':'submit'}
:param request:
:param args:
:param kwargs:
:return:
"""
editable_data = str(request.body, encoding='utf-8')
if editable_data:
editable_data = json.loads(editable_data) ## for list editable
del editable_data[0]
#print('反射',editable_data) # [{'confirm_user': '7', 'confirm_date': '1899-12-13 09:50:00+00:00', 'id': '2'}]
for row_data in editable_data:
obj_id = row_data.get('id')
if obj_id:
#print("editable data", row_data, list(row_data.keys()))#['id', 'confirm_user', 'confirm_date']
obj = self.model_class.objects.get(id=obj_id)
model_form = self.create_list_editable_model_form(list(row_data.keys()))
form_obj = model_form(instance=obj, data=row_data)
if form_obj.is_valid():
form_obj.save()
muti_editable_save.attr_dict = {'text':'批量保存','id':'submit'}

这样很容易就实现了list_editable的保存,而且以后如果想通过action_list各个功能的话,指的,可以选择ajax发送数据,或者表单发送,只需要在后台中给对应的处理函数赋值相应的id属性就可以了,值得注意的是,如果使用ajax功能的,就必须加上display_checkbox(),因为取id的时候就是通过checkbox中来获取的,这就是列表页面的主要功能了。

												

stark组件之显示页面内容搭建(六)的更多相关文章

  1. stark组件之删除页面内容搭建(八)

    删除页面没有太多的内容和功能 def del_view(self, request,pk,*args,**kwargs): """ 处理删除表弟 :param reque ...

  2. stark组件之显示页面搭建(四)

    页面搭建包括第一如何获取前端传过来的数据,第二如何在前端渲染出对应标签. 一.后台获取数据并进行处理 在路由系统中,每一个路由都对应着一个处理函数,如下所示: def wrapper(self, fu ...

  3. stark组件之添加、修改页面内容搭建(七)

    如何快速的进行数据的添加以及修改呢?modelform来实现是可以达到效果的,在这里就是应用了modelform,每一个表都不同,所以需要创建不同的modelform. def get_model_f ...

  4. stark组件之pop页面,按钮,url,页面

      1.Window open() 方法 2.admin的pop添加按钮 3.stark之pop功能 3.知识点总结 4.coding代码 1.Window open() 方法 效果图   2.adm ...

  5. 24.stark组件全部

    admin组件: 博客里面的图片的是在太难弄了,有大哥会弄给我贴一片博客,我一个一个加太累了,没有加 admin参考:https://www.cnblogs.com/yuanchenqi/articl ...

  6. crm 使用stark组件

    # Create your models here. from django.db import models class Department(models.Model): "" ...

  7. winform里面网页显示指定内容

    今天有个同事问了一下我,怎么在winform里面打开网页啊?我们都是基于C/S的开发,很少接触winform,所以我当时就懵了,实在不知道怎么回答,所以索性说不知道.但是我又想了想,这个应该是个很简单 ...

  8. stark组件开发之列表页面应用示例

    已经解决的,自定义的扩展函数,功能.但是 不可能返回. 一个 固定的页面把!  应该是,点击那条 记录之后的编辑, 就会跳转到相应的,编辑页面.所以 这个标签的  <a href="/ ...

  9. python 全栈开发,Day112(内容回顾,单例模式,路由系统,stark组件)

    一.内容回顾 类可否作为字典的key 初级 举例: class Foo(object): pass _registry = { Foo:123 } print(_registry) 执行输出: {&l ...

随机推荐

  1. bzoj 1834: [ZJOI2010]network 网络扩容【最大流+最小费用最大流】

    第一问直接跑最大流即可.建图的时候按照费用流建,费用为0. 对于第二问,在第一问dinic剩下的残量网络上建图,对原图的每条边(i,j),建(i,j,inf,cij),表示可以用c的花费增广这条路.然 ...

  2. 洛谷 P2762 太空飞行计划问题 【最大权闭合子图+最小割】

    --一道难在读入的题. 最后解决方案直接getline一行然后是把读优拆掉放进函数,虽然很丑但是过了. 然后就是裸的最大权闭合子图了,把仪器当成负权点向t连流量为其价格的边,s向实验连流量为实验报酬的 ...

  3. [Usaco2006 Open]County Fair Events 参加节日庆祝

    Description Farmer John has returned to the County Fair so he can attend the special events (concert ...

  4. ASP.NET MVC 实现伪静态

    1  什么是伪静态? 现在很多门户网站或者各大电商平台的网站的链接最后都是.htm或者.htm结尾,那么他们的网页真的是静态的html吗?拿京东来说,有无数个页面都都Html,在商品每时每刻都可能被更 ...

  5. HBuilder的默认工作空间的修改

    HBuilder的默认工作空间的修改并不像其他ide一样,在设置里进行更改,而是在工具中进行设置. 1.单击菜单栏“工具”,选择“变更默认代码存放目录” 2.进行修改即可.

  6. 支付宝添加scheme的方法

    点击项目名称,点击“Info”选项卡,在“URL Types”选项中,点击“+”,在“URL Schemes”中输入“myAlipay”.“myAlipay”来自于文件“APViewControlle ...

  7. 12c debug 转 12C 连接CDB和PDB

    来源:David Dai -- Focus on Oracle 连接到CDB 12c debug 和普通实例一样的连接. 指定ORACLE_SID 以后可以使用OS认证,也可以使用密码进行连接. [o ...

  8. E. Comments dfs模拟

    http://codeforces.com/contest/747/problem/E 首先,把字符串变成这个样子. hello,2,ok,0,bye,0,test,0,one,1,two,2,a,0 ...

  9. sed简单脚本练习

    sed脚本的执行顺序可以简记为:Read,Execute,Print,Repeat(读取,执行,打印,重复)简称REPR 分析脚本的执行顺序: l 读取一行到模式空间(sed内部的一个临时缓存,用于存 ...

  10. Oracle 的备份和恢复

    Oracle数据库有三种标准的备份方法,它们分别是导出/导入(EXP/IMP).热备份和冷备 份.导出备件是一种逻辑备份,冷备份和热备份是物理备份. 一. 导出/导入(Export/Import) 利 ...