这里要实现点击对应的表名称,显示具体表的详细内容,大致的流程是:
前端显示各个表名,如下:
- <tbody>
- {% for table_name,admin in app_tables.items %}
- <tr class="border-bottom">
- <td style="padding-bottom: 3px;padding-top: 3px;">
- <a href="{% url 'table_objs' app_name table_name %}">{% render_app_name admin %}a>
- td>
- <td style="padding-bottom: 3px;padding-top: 3px;">Addtd>
- <td style="padding-bottom: 3px;padding-top: 3px;">Changetd>
- tr>
- {% endfor %}
- tbody>
主要就是:{% render_app_name admin %},
对应表名的url被解析成/应用名/表名,如/plcrm/customer形式,对应的在路由项中有如下路由:path('
- def display_table_objs(req,app_name,table_name):
- print("====>",app_name,table_name)
-
- admin_class = mytestapp_admin.enable_admins[app_name][table_name]
-
- print('-----.....>',admin_class,admin_class.model.__name__)
-
- return render(req,"mytestapp/table_objs.html",{"admin_class":admin_class})
通过enable_admins字典获取到对应的admin_class,然后传递到前端,即table_objs.html,然后在全端展示各字段:
-
- {% for columndata in admin_class.model.objects.all %}
- <tr>
- <td>{{ columndata }}td>
- tr>
- {% endfor %}
上面的代码运行时会出现错误:

在网上查询,一般是这样解释的:出现这种错误是因为调用模型对象时使用了变量名,而不是对象名(模型类),也就是说必须使用对象名,如这里应该是Customer,但是后台传递过来的,即视图函数中带的数据就一个admin_class,这里就是CustomerAdmin,以通常的理解,CustomerAdmin中有model属相,这个属性的值是Customer,那就应该可以的,实际不行。
也就是说,在模板中使用models类取数时,必须使用类名称,不能使用变量名。所以,要使用Customer类来取对应表中的数据,但是视图函数要传递数据给模板,是用的字典,也就是模板使用的是key,无法使用类名,从而也就无法直接在模板中使用model类直接取数,需要在视图函数中查询出数据,传递给模板,或者在模板中使用自定义标签,来完成取数的功能。
第一种:修改视图函数,在视图函数中获取数据,然后传递给模板:
- def display_table_objs(req,app_name,table_name):
-
- admin_class = mytestapp_admin.enable_admins[app_name][table_name]
- models_data = admin_class.model.objects.all()
- return render(req,"mytestapp/table_objs.html",{"admin_class":admin_class,"model_class_name":admin_class.model.__name__,'model_data':models_data})
传给模板的model_data是查询出的数据QuerySet型数据,在模板中:
- {% for kk in model_data %}
- <tr>
- <td>{{ kk.name }} | {{ kk.qq }}td>
- tr>
- {% endfor %}
因为前端显示的是admin_class中的list_display中定义的字段,所以,修改一下视图函数的中取数:models_data = admin_class.model.objects.values_list(*admin_class.list_display)
前端:
- {% for kk in model_data %}
- <tr>
- {% for gg in kk %}
- <td>{{ gg }} td>
- {% endfor %}
- tr>
- {% endfor %}
第二种,使用自定义标签,也可以有两种处理方法
1、标签可以按照admin_class中的list_display取数,传递给前端,前端遍历生成html
- @register.simple_tag
- def get_query_sets_1(admin_class):
- return admin_class.model.objects.values_list(*admin_class.list_display)
前端循环:
- <tbody>
- {% get_query_sets_1 admin_class as query_sets %}
- {% for obj in query_sets %}
- <tr>
- {% for obj_item in obj %}
- <td colspan="6">{{ obj_item }}td>
- {% endfor %}
- tr>
- {% endfor %}
- tbody>
2、标签返回model中全部数据,再定义一个标签,按照list_display组装这些数据,生成一个html字符串,传递个前端。
- @register.simple_tag
- def get_query_sets_1(admin_class):
- return admin_class.model.objects.all()
-
-
- @register.simple_tag
- def build_table_row(obj,admin_class):
- row_ele = ""
- for row_data in obj:
- row_ele = row_ele +"
"- for column in admin_class.list_display:
- column_data = getattr(row_data,column)
- row_ele += "
%s "%column_data - row_ele = row_ele + "
" - return mark_safe(row_ele)
前端:
- <tbody>
- {% get_query_sets_1 admin_class as query_sets %}
- {% build_table_row query_sets admin_class %}
-
- tbody>
这种方法有一个问题,对于tags,使用getattr()取出的是plcrm.Tag.None,而使用第一种和视图函数返回,都是数值。
还有一个共同的问题,就是model类中有choices项的,对应的应该显示choices中的值,如source,这里都是显示数字,正常,显示说明文字,即对应的choices中的说明。
只能使用自定义标签方法的第二种:在组装标签时判断与替换
- @register.simple_tag
- def build_table_row(obj,admin_class):
- row_ele = ""
- print("===///:::",obj)
- for row_data in obj:
- row_ele = row_ele +"
"- for column in admin_class.list_display:
- field_obj = row_data._meta.get_field(column)
- if field_obj.choices:
- column_data = getattr(row_data,"get_%s_display"%column)()
- else:
- column_data = getattr(row_data,column)
- row_ele += "
%s "%column_data - row_ele = row_ele + "
" - print(row_ele)
- return mark_safe(row_ele)
显示如下:

source字段显示正确了,但是tags不正确,tags是manytomany的外键,修改一下:
- @register.simple_tag
- def build_table_row(obj,admin_class):
- row_ele = ""
- print("===///:::",obj)
- for row_data in obj:
- row_ele = row_ele +"
"- for column in admin_class.list_display:
- field_obj = row_data._meta.get_field(column)
- if field_obj.choices:
- column_data = getattr(row_data,"get_%s_display"%column)()
- else:
- column_data = getattr(row_data,column)
- field_obj1 = getattr(row_data,column)
- if hasattr(field_obj1,'values'):
- s = ""
- dic1 = field_obj1.values()[0]
- print(type(dic1),dic1)
- for v in dic1.values():
- s = s + str(v) + ';'
- column_data = s
-
- row_ele += "
%s "%column_data - row_ele = row_ele + "
" - print(row_ele)
- return mark_safe(row_ele)
对于外键,主要是判断字段是否有values方法(注意跟遍历字典时的values区别)。
