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

Posted kaoa000

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python入门自学进阶-Web框架——24DjangoAdmin项目应用-定制页面2相关的知识,希望对你有一定的参考价值。

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

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

<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;">Add</td>
                      <td style="padding-bottom: 3px;padding-top: 3px;">Change</td>
                    </tr>
                    % endfor %
</tbody>

主要就是:<a href="% url 'table_objs' app_name table_name %">% render_app_name admin %</a>,

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

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,然后在全端展示各字段:

<!-- 表体中按照表头的字段,循环显示表中的数据 -->
              <!-- 因为函数传递的是admin_class,而admin_class中有model属性,保存了对应的model类,感觉可以直接如下取数显示-->
                % 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 +"<tr>"
        for column in admin_class.list_display:
            column_data = getattr(row_data,column)
            row_ele += "<td colspan='6'>%s</td>"%column_data
        row_ele = row_ele + "</tr>"
    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 +"<tr>"
        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 += "<td colspan='6'>%s</td>"%column_data
        row_ele = row_ele + "</tr>"
    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 +"<tr>"
        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 += "<td colspan='6'>%s</td>"%column_data
        row_ele = row_ele + "</tr>"
    print(row_ele)
    return mark_safe(row_ele)

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

以上是关于Python入门自学进阶-Web框架——24DjangoAdmin项目应用-定制页面2的主要内容,如果未能解决你的问题,请参考以下文章

Python入门自学进阶-Web框架——18FormModelForm

Python入门自学进阶-Web框架——18FormModelForm

Python入门自学进阶-Web框架——20Django其他相关知识2

Python入门自学进阶-Web框架——2Django初识

Python入门自学进阶-Web框架——3Django的URL配置

Python入门自学进阶-Web框架——21DjangoAdmin项目应用