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

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

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


                    {% for  table_name,admin in app_tables.items %}

                          {% render_app_name admin %}

                      Add
                      Change

                    {% endfor %}

主要就是:{% 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 %}

                        {{ columndata }}

                {% endfor %}

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

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

在网上查询,一般是这样解释的:出现这种错误是因为调用模型对象时使用了变量名,而不是对象名(模型类),也就是说必须使用对象名,如这里应该是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 %}

                {{ kk.name }} | {{ kk.qq }}

{% endfor %}

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

前端:

 {% for kk in model_data %}

          {% for gg in kk %}
               {{ gg }}
          {% endfor %}

{% 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)

前端循环:


       {% get_query_sets_1 admin_class as query_sets %}
       {% for obj in query_sets %}

                  {% for obj_item in obj %}
                      {{ obj_item }}
                  {% endfor %}

       {% endfor %}

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)

前端:


                {% get_query_sets_1 admin_class as query_sets %}
                {% build_table_row query_sets admin_class %}

这种方法有一个问题,对于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)

显示如下:

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

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区别)。

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

Original: https://blog.csdn.net/kaoa000/article/details/127439321
Author: kaoa000
Title: Python入门自学进阶-Web框架——24、DjangoAdmin项目应用-定制页面2

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/735306/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球