美文网首页Python Web开发学习
【CRM客户关系管理】07.自动发现APP注册并显示列表

【CRM客户关系管理】07.自动发现APP注册并显示列表

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

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

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

    注册APP列表显示

    从这儿起,难度就有增加了

    自动发现app和注册

    可以实现页面显示所有APP和对应的表名

    创建app_setup.py

    djadmin应用下创建app_setup.py文件

    from django import conf
    
    
    def djadmin_auto_discover():
        for app_name in conf.settings.INSTALLED_APPS:
            try:
                # 去每个app下执行djadmin.py文件
                # crm.apps.CrmConfig和crm需要做判定
                mod = __import__('{}.djadmin'.format(app_name if 'Config' not in app_name else app_name.split('.')[0]))
                # 打印每个app已注册的model名字
                print(mod.djadmin)
                # 会打印:<module 'crm.djadmin' from 'E:\\Sync\\OneDrive\\PycharmProjects\\DjangoCRM\\crm\\djadmin.py'>
            except ImportError:
                pass
    

    动态获取settings里面所有添加的app名字

    Python __import__() 函数,具体用法查看 http://www.runoob.com/python/python-func-__import__.html

    • __import__() 函数用于动态加载类和函数 。
    • 如果一个模块经常变化就可以使用 __import__() 来动态载入。

    返回全局字典

    在djadmin应用下创建sites.py文件

    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
    
            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()
    

    应用下创建djadmin.py文件

    crm应用下创建djadmin.py文件,用于注册模型

    from djadmin.sites import site
    from crm import models
    
    print('crm models...')
    
    
    # 注册model
    class CustomerInfoAdmin(object):
        list_display = ['name', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'created_time']
        list_filter = ['source', 'consultant', 'status', 'created_time']
        search_fields = ['contact', 'consultant__name']
    
    
    site.register(models.CustomerInfo, CustomerInfoAdmin)
    

    djadmin应用下添加执行入口

    修改djadmin应用下的views.py文件,增加

    from djadmin import app_setup
    
    app_setup.djadmin_auto_discover()
    from djadmin.sites import site
    
    print('site:', site.enable_admins)
    

    当程序一启动就会打印入口的信息

    manage.py runserver 8000
    Performing system checks...
    
    crm models...
    <module 'crm.djadmin' from 'E:\\Sync\\OneDrive\\PycharmProjects\\DjangoCRM\\crm\\djadmin.py'>
    site: {'crm': {'customerinfo': <class 'crm.djadmin.CustomerInfoAdmin'>}}
    

    会根据sites.py的配置显示字典信息。

    前端页面显示

    修改djadmin应用下的index视图,增加视图的参数

    @login_required
    def index(request):
        return render(request, 'djadmin/index.html',
                      {
                          'site': site
                      })
    

    修改djadmin/templates/djadmin/index.html页面显示

    字典样式:{'crm': {'customerinfo': <class 'crm.djadmin.CustomerInfoAdmin'>, 'userprofile': <class 'djadmin.djadmin_base.BaseDjAdmin'>, ...},...}

    模板中进行遍历

    {% extends 'djadmin/base.html' %}
    
    {% block title %}
        主页 - 后台管理
    {% endblock %}
    
    {% block content %}
        <h1 class="page-header">所有应用</h1>
        {% for app_name, app_models in site.enable_admins.items %}
            <table class="table table-striped">
                <thead>
                <tr>
                    <th>{{ app_name }}</th>
                </tr>
                </thead>
                <tbody>
                {% for model_name in app_models %}
                    <tr>
                        <td><a href="#">{{ model_name }}</a></td>
                        <td>增加</td>
                        <td>修改</td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        {% endfor %}
    
    {% endblock %}
    
    image.png

    修改crm应用下的djadmin.py文件,增加注册其他models

    from djadmin.sites import site
    from crm import models
    
    print('crm models...')
    
    
    # 注册model
    class CustomerInfoAdmin(object):
        list_display = ['name', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'created_time']
        list_filter = ['source', 'consultant', 'status', 'created_time']
        search_fields = ['contact', 'consultant__name']
    
    
    site.register(models.CustomerInfo, CustomerInfoAdmin)
    
    site.register(models.Role)
    site.register(models.Menu)
    site.register(models.UserProfile)
    

    刷新 http://127.0.0.1:8000/djadmin/ 页面

    image.png

    如何在视图中获取模型实例

    注册模型类属性赋值

    修改djadmin应用下的sites.py文件,增加admin_class.model = model_class

    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)
    
            # 把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()
    

    此时重新运行项目会报错

    AttributeError: 'NoneType' object has no attribute 'model'
    

    是因为我们在注册model的时候,有的写了自定义的model类site.register(models.CustomerInfo, CustomerInfoAdmin),有的没写site.register(models.Role),而我们都统一的赋值,导致那些没写自定义model类(空的)赋值的时候就会报NoneType错误

    django自带的自定义admin类的写法继承了ModelAdmin,那注册的时候为什么有的没写自定义admin类没有报错呢?是因为继承的ModelAdmin帮我们写了(里面其实都定义为空了),我们模仿django admin的写法,也写个父类。

    注册模型类继承

    在djdadmin应用下新建个djadmin_base.py,写个父类

    # djadmin/djadmin_base.py
    
    
    class BaseDjAdmin(object):
        pass
    

    修改crm应用下的djadmin.py文件,继承BaseDjAdmin

    from djadmin.sites import site
    from crm import models
    from djadmin.djadmin_base import BaseDjAdmin
    
    print('crm models...')
    
    
    # 注册model
    class CustomerInfoAdmin(BaseDjAdmin):  # 不使用object,直接继承BaseDjAdmin
        list_display = ['name', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'created_time']
        list_filter = ['source', 'consultant', 'status', 'created_time']
        search_fields = ['contact', 'consultant__name']
    
    
    site.register(models.CustomerInfo, CustomerInfoAdmin)
    
    site.register(models.Role)
    site.register(models.Menu)
    site.register(models.UserProfile)
    

    修改djadmin应用下的sites.py文件

    如果传值site.register(models.CustomerInfo, CustomerInfoAdmin)那么admin_class就等于CustomerInfoAdmin;如果没有传值site.register(models.Role),就使用默认值admin_class=BaseAdmin

    from djadmin.djadmin_base import BaseDjAdmin
    
    
    class AdminSite(object):
        def __init__(self):
            self.enable_admins = {}
    
        # 两个参数,一个表名,一个自定义的admin类
        def register(self, model_class, admin_class=BaseDjAdmin):
            """注册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)
    
            # 把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()
    
    

    访问 http://127.0.0.1:8000/djadmin/ 页面也是正常显示的

    image.png

    会显示应用的名称,和已经注册的model

    image.png

    相关文章

      网友评论

        本文标题:【CRM客户关系管理】07.自动发现APP注册并显示列表

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