美文网首页Python Web开发学习
【CRM客户关系管理】08.取出app中model的值,根据li

【CRM客户关系管理】08.取出app中model的值,根据li

作者: 吾星喵 | 来源:发表于2018-11-25 19:53 被阅读0次

    个人博客,欢迎查看:https://blog.starmeow.cn/

    Github地址:https://github.com/xyliurui/DjangoCRM

    根据注册models配置生成数据列表

    取出app中model的值

    models详情视图table_detail

    在djadmin应用的views.py新建视图

    @login_required
    def table_detail(request, app_name, model_name):
        """取出指定model里的数据返回到前端"""
        # 拿到admin_class后,通过它获取model
        admin_class = site.enable_admins[app_name][model_name]
        queryset = admin_class.model.objects.all()
        print(queryset)
    
        return render(request, 'djadmin/table_detail.html', locals())
    

    创建详情的模板table_detail.html

    {% extends 'djadmin/base.html' %}
    
    {% block title %}
        数据表详情 - 后台管理
    {% endblock %}
    
    {% block content %}
        <h1 class="page-header">应用 - {{ app_name }}</h1>
        {{ queryset }}
        <table class="table table-striped">
            <thead>
            <tr>
                <th>{{ app_name }}</th>
            </tr>
            </thead>
            <tbody>
    
            </tbody>
        </table>
    
    {% endblock %}
    

    models详情url

    修改djadmin应用下的urls,增加详情路由

    from django.urls import path
    from djadmin.views import index, user_login, user_logout, table_detail
    
    app_name = 'djadmin'
    
    urlpatterns = [
        path('login/', user_login, name='user_login'),  # djAdmin登录
        path('logout/', user_logout, name='user_logout'),  # djAdmin登出
        path('', index, name='index'),  # djAdmin主页
        path('<str:app_name>/<str:model_name>/', table_detail, name='table_detail'),  # 数据表详情
    ]
    

    修改index.html增加详情链接

    <td><a href="{% url 'djadmin:table_detail' app_name=app_name model_name=model_name %}">{{ model_name }}</a></td>
    

    访问这四个页面的详情链接

    image.png
    <QuerySet [<CustomerInfo: 测试>]>
    [10/Nov/2018 10:49:23] "GET /djadmin/crm/customerinfo/ HTTP/1.1" 200 4592
    <QuerySet [<UserProfile: LR>]>
    [10/Nov/2018 10:49:26] "GET /djadmin/crm/role/ HTTP/1.1" 200 4587
    <QuerySet [<UserProfile: LR>]>
    [10/Nov/2018 10:49:28] "GET /djadmin/crm/menu/ HTTP/1.1" 200 4587
    <QuerySet [<UserProfile: LR>]>
    [10/Nov/2018 10:49:31] "GET /djadmin/crm/userprofile/ HTTP/1.1" 200 4587
    

    判断注册类实例化

    最终打印出来的queryset = admin_class.model.objects.all()有三个是相同的,也就是没注册三个model里面得到值是一样

    原因分析:因为没注册的三个mdoel都共享同一个BaseDjAdmin内存对象(三个model内存地址一样),我们只需要实例化就可以了(实例化后就都有单独的内存空间了)

    修改djadmin/sites.py文件,增加判断实例化对象

    from djadmin.djadmin_base import BaseDjAdmin
    
    
    class AdminSite(object):
        def __init__(self):
            self.enable_admins = {}
    
        # 两个参数,一个表名,一个自定义的admin类
        def register(self, model_class, admin_class=None):
            """注册admin表"""
    
            # print('register',model_class,admin_class)
            # 获取app名字
            app_name = model_class._meta.app_label
            # 获取表名
            model_name = model_class._meta.model_name
            # 获取表别名
            # model_verbose_name = model_class._meta.verbose_name
            # print(model_verbose_name)
    
            if admin_class:
                # 如果写了注册的类,就实例化自己
                admin_class = admin_class()
            else:
                # 如果没有写注册的类,就用BaseDjAdmin实例化,防止使用相同的内存地址
                admin_class = BaseDjAdmin()
    
            # 把model_class赋值给了admin_class,然后在视图中可以通过admin_class找到对应的model类(表名字)
            admin_class.model = model_class
    
            if app_name not in self.enable_admins:
                self.enable_admins[app_name] = {}
            self.enable_admins[app_name][model_name] = admin_class
    
    
    # 实例化,就可以调用register方法
    site = AdminSite()
    
    

    然后访问各个链接,都是返回各自的查询集了

    [10/Nov/2018 11:11:22] "GET /djadmin/ HTTP/1.1" 200 5415
    <QuerySet [<CustomerInfo: 测试>]>
    [10/Nov/2018 11:11:24] "GET /djadmin/crm/customerinfo/ HTTP/1.1" 200 4592
    <QuerySet [<Role: 销售>, <Role: admin>]>
    [10/Nov/2018 11:11:27] "GET /djadmin/crm/role/ HTTP/1.1" 200 4605
    <QuerySet [<Menu: 客户库>, <Menu: 主页(绝对)>, <Menu: 主页(动态)>]>
    [10/Nov/2018 11:11:31] "GET /djadmin/crm/menu/ HTTP/1.1" 200 4655
    <QuerySet [<UserProfile: LR>]>
    [10/Nov/2018 11:11:35] "GET /djadmin/crm/userprofile/ HTTP/1.1" 200 4587
    

    根据list_display配置生成数据列表

    通过自定义的admin_class类,循环出list_display所有的列

    在crm应用下djadmin.py配置中list_display = ['name', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'created_time']

    显示表头

    修改table_detail.html遍历出上方的列表

    {% extends 'djadmin/base.html' %}
    
    {% block title %}
        数据表详情 - 后台管理
    {% endblock %}
    
    {% block content %}
        <h1 class="page-header">应用 - {{ app_name }}</h1>
        {{ queryset }}
        <table class="table table-striped">
            <thead>
            <tr>
                {% for display_field in admin_class.list_display %}
                    <th>{{ display_field }}</th>
                {% endfor %}
            </tr>
            </thead>
            <tbody>
    
            </tbody>
        </table>
    {% endblock %}
    
    image.png

    下面通过自定义模板标签显示表头的别名,也就是模型中定义的verbose_name

    自定义模板标签

    djadmin应用下新建python Package,取名为templatetags,然后再这个包内创建djadmin_tags.py文件

    from django.template import Library
    from django.utils.safestring import mark_safe
    
    
    register = Library()
    
    
    # 显示模型表的中文名称
    @register.simple_tag
    def build_table_head_name(admin_class):
        th = ''
        for display_field in admin_class.list_display:
            # 获取列中的字段对象
            display_field_obj = admin_class.model._meta.get_field(display_field)
            # print(display_field_obj.verbose_name)
            tmp = "<th>{}</th>".format(display_field_obj.verbose_name)
            th += tmp
        return mark_safe(th)
    
    
    # 显示表数据
    @register.simple_tag
    def build_table_body(obj, admin_class):
        """
        生成一条记录的html元素
        :param obj: 一个模型查询集中的一个对象
        :param admin_class: 自定义注册的类
        :return: 得到这个对象要求显示的所有列
        """
        td = ''
        for display_field_name in admin_class.list_display:
            # 根据属性名,获取对象的属性值,两个参数,一个对象obj,一个列名
            display_field_data = getattr(obj, display_field)  # 获取一个对象的属性值,例如<CustomerInfo: 小东>对象,得到他的name属性,值为小东
            tmp = "<td>{}</td>".format(display_field_data)
            td += tmp
        return mark_safe(td)
    

    数据列表中使用模板标签

    • 首先导入{% load djadmin_tags %}
    • 遍历查询集,得到每一个对象
    • 将对象和自定义的注册类两个参数传入到模板标签
    {% extends 'djadmin/base.html' %}
    
    {% load djadmin_tags %}
    
    {% block title %}
        数据表详情 - 后台管理
    {% endblock %}
    
    {% block content %}
        <h1 class="page-header">应用 - {{ app_name }}</h1>
        {{ queryset }}
        <table class="table table-striped">
            <thead>
            <tr>
                <!--
                {% for display_field in admin_class.list_display %}
                    <th>{{ display_field }}</th>
                {% endfor %}
                -->
                {% build_table_head_name admin_class %}
            </tr>
            </thead>
            <tbody>
                {% for obj in queryset %}
                    <tr>
                        {% build_table_body obj admin_class %}
                    </tr>
                {% endfor %}
            </tbody>
        </table>
    {% endblock %}
    

    现在访问 http://127.0.0.1:8000/djadmin/crm/customerinfo/ 就可以看到相关的数据

    image.png

    但是其中的选择项的列是数字,比如status显示的1,2,想要显示未报名已报名

    修改模板标签选择项显示方式

    因为有的字段有choices,有的字段没有choices,需要添加一个判断

    • models.CustomerInfo._meta.fields 获取model所有字段的对象
    • models.CustomerInfo._meta.get_field('status') 取一个字段的对象
    • get_xxxx_display 显示choices里面的值

    继续修改模板标签build_table_body(obj, admin_class)函数

    # 显示表数据
    @register.simple_tag
    def build_table_body(obj, admin_class):
        """
        生成一条记录的html元素
        :param obj: 一个模型查询集中的一个对象
        :param admin_class: 自定义注册的类
        :return: 得到这个对象要求显示的所有列
        """
        td = ''
        for display_field in admin_class.list_display:
            # 获取列中的字段对象
            display_field_obj = admin_class.model._meta.get_field(display_field)
            # print(display_field_obj)
            # 字段对象choices方法,如果有choices,则使用get_xxx_display
            if display_field_obj.choices:
                print('get_{}_display'.format(display_field))
                display_field_data = getattr(obj, 'get_{}_display'.format(display_field))()  # 使用get_xxx_display()需要带括号,调用函数执行结果,而不带括号得到的是函数对象
            else:
                # 根据属性名,获取对象的属性值,两个参数,一个对象obj,一个列名
                display_field_data = getattr(obj, display_field)  # 获取一个对象的属性值,例如<CustomerInfo: 小东>对象,得到他的name属性,值为小东
            tmp = "<td>{}</td>".format(display_field_data)
            td += tmp
        return mark_safe(td)
    

    现在刷新 http://127.0.0.1:8000/djadmin/crm/customerinfo/ 页面

    image.png

    所有选择项就变成可识别的内容了。

    相关文章

      网友评论

        本文标题:【CRM客户关系管理】08.取出app中model的值,根据li

        本文链接:https://www.haomeiwen.com/subject/onhmqqtx.html