• Python入门自学进阶-Web框架——24、DjangoAdmin项目应用-定制页面2


    这里要实现点击对应的表名称,显示具体表的详细内容,大致的流程是:

    前端显示各个表名,如下:

    1. <tbody>
    2. {% for table_name,admin in app_tables.items %}
    3. <tr class="border-bottom">
    4. <td style="padding-bottom: 3px;padding-top: 3px;">
    5. <a href="{% url 'table_objs' app_name table_name %}">{% render_app_name admin %}a>
    6. td>
    7. <td style="padding-bottom: 3px;padding-top: 3px;">Addtd>
    8. <td style="padding-bottom: 3px;padding-top: 3px;">Changetd>
    9. tr>
    10. {% endfor %}
    11. tbody>

    主要就是:{% render_app_name admin %}

    对应表名的url被解析成/应用名/表名,如/plcrm/customer形式,对应的在路由项中有如下路由:path('//',views.display_table_objs,name="table_objs"),请求处理的函数是views.display_table_objs:

    1. def display_table_objs(req,app_name,table_name):
    2. print("====>",app_name,table_name)
    3. admin_class = mytestapp_admin.enable_admins[app_name][table_name]
    4. print('-----.....>',admin_class,admin_class.model.__name__)
    5. return render(req,"mytestapp/table_objs.html",{"admin_class":admin_class})

    通过enable_admins字典获取到对应的admin_class,然后传递到前端,即table_objs.html,然后在全端展示各字段:

    1. {% for columndata in admin_class.model.objects.all %}
    2. <tr>
    3. <td>{{ columndata }}td>
    4. tr>
    5. {% endfor %}

    上面的代码运行时会出现错误:

     在网上查询,一般是这样解释的:出现这种错误是因为调用模型对象时使用了变量名,而不是对象名(模型类),也就是说必须使用对象名,如这里应该是Customer,但是后台传递过来的,即视图函数中带的数据就一个admin_class,这里就是CustomerAdmin,以通常的理解,CustomerAdmin中有model属相,这个属性的值是Customer,那就应该可以的,实际不行。

    也就是说,在模板中使用models类取数时,必须使用类名称,不能使用变量名。所以,要使用Customer类来取对应表中的数据,但是视图函数要传递数据给模板,是用的字典,也就是模板使用的是key,无法使用类名,从而也就无法直接在模板中使用model类直接取数,需要在视图函数中查询出数据,传递给模板,或者在模板中使用自定义标签,来完成取数的功能。

    第一种:修改视图函数,在视图函数中获取数据,然后传递给模板:

    1. def display_table_objs(req,app_name,table_name):
    2. admin_class = mytestapp_admin.enable_admins[app_name][table_name]
    3. models_data = admin_class.model.objects.all()
    4. 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型数据,在模板中:

    1. {% for kk in model_data %}
    2. <tr>
    3. <td>{{ kk.name }} | {{ kk.qq }}td>
    4. tr>
    5. {% endfor %}

    因为前端显示的是admin_class中的list_display中定义的字段,所以,修改一下视图函数的中取数:models_data = admin_class.model.objects.values_list(*admin_class.list_display)

    前端:

    1. {% for kk in model_data %}
    2. <tr>
    3. {% for gg in kk %}
    4. <td>{{ gg }} td>
    5. {% endfor %}
    6. tr>
    7. {% endfor %}

    第二种,使用自定义标签,也可以有两种处理方法

    1、标签可以按照admin_class中的list_display取数,传递给前端,前端遍历生成html

    1. @register.simple_tag
    2. def get_query_sets_1(admin_class):
    3. return admin_class.model.objects.values_list(*admin_class.list_display)

    前端循环:

    1. <tbody>
    2. {% get_query_sets_1 admin_class as query_sets %}
    3. {% for obj in query_sets %}
    4. <tr>
    5. {% for obj_item in obj %}
    6. <td colspan="6">{{ obj_item }}td>
    7. {% endfor %}
    8. tr>
    9. {% endfor %}
    10. tbody>

    2、标签返回model中全部数据,再定义一个标签,按照list_display组装这些数据,生成一个html字符串,传递个前端。

    1. @register.simple_tag
    2. def get_query_sets_1(admin_class):
    3. return admin_class.model.objects.all()
    4. @register.simple_tag
    5. def build_table_row(obj,admin_class):
    6. row_ele = ""
    7. for row_data in obj:
    8. row_ele = row_ele +""
    9. for column in admin_class.list_display:
    10. column_data = getattr(row_data,column)
    11. row_ele += "%s"%column_data
    12. row_ele = row_ele + ""
    13. return mark_safe(row_ele)

    前端:

    1. <tbody>
    2. {% get_query_sets_1 admin_class as query_sets %}
    3. {% build_table_row query_sets admin_class %}
    4. tbody>

    这种方法有一个问题,对于tags,使用getattr()取出的是plcrm.Tag.None,而使用第一种和视图函数返回,都是数值。

    还有一个共同的问题,就是model类中有choices项的,对应的应该显示choices中的值,如source,这里都是显示数字,正常,显示说明文字,即对应的choices中的说明。

    只能使用自定义标签方法的第二种:在组装标签时判断与替换

    1. @register.simple_tag
    2. def build_table_row(obj,admin_class):
    3. row_ele = ""
    4. print("===///:::",obj)
    5. for row_data in obj:
    6. row_ele = row_ele +""
    7. for column in admin_class.list_display:
    8. field_obj = row_data._meta.get_field(column)
    9. if field_obj.choices:
    10. column_data = getattr(row_data,"get_%s_display"%column)()
    11. else:
    12. column_data = getattr(row_data,column)
    13. row_ele += "%s"%column_data
    14. row_ele = row_ele + ""
    15. print(row_ele)
    16. return mark_safe(row_ele)

    显示如下:

     

     source字段显示正确了,但是tags不正确,tags是manytomany的外键,修改一下:

    1. @register.simple_tag
    2. def build_table_row(obj,admin_class):
    3. row_ele = ""
    4. print("===///:::",obj)
    5. for row_data in obj:
    6. row_ele = row_ele +""
    7. for column in admin_class.list_display:
    8. field_obj = row_data._meta.get_field(column)
    9. if field_obj.choices:
    10. column_data = getattr(row_data,"get_%s_display"%column)()
    11. else:
    12. column_data = getattr(row_data,column)
    13. field_obj1 = getattr(row_data,column)
    14. if hasattr(field_obj1,'values'):
    15. s = ""
    16. dic1 = field_obj1.values()[0]
    17. print(type(dic1),dic1)
    18. for v in dic1.values():
    19. s = s + str(v) + ';'
    20. column_data = s
    21. row_ele += "%s"%column_data
    22. row_ele = row_ele + ""
    23. print(row_ele)
    24. return mark_safe(row_ele)

    对于外键,主要是判断字段是否有values方法(注意跟遍历字典时的values区别)。

  • 相关阅读:
    首个ChatGPT机器人- Figure 01;李开复旗下零一万物推出Yi系列AI大模型API
    Kotlin:崛起中的下一代编程语言
    Java Math.asin()方法具有什么功能呢?
    org.springframework.transaction.annotation.Transactional 简单使用示例
    C++消息总线Mozart:timer类实现
    【Spring Boot】Web开发 — Web开发简介
    Vue-SplitPane可拖拽分隔面板(随意拖动div)
    OpenShift 4 - 在 OpenShift 上安装 GitLab
    dpdk实现dns
    EPDM和钉钉集成审批工作—移动端直接处理审批节点,高效协同!
  • 原文地址:https://blog.csdn.net/kaoa000/article/details/127439321