zoukankan      html  css  js  c++  java
  • django-cms 代码研究(八)app hooks

    app钩子,啥玩意呢?

    就是把现有的app,集成到cms的一种手段。

    有两种实现方式:

    1) 定义cms_app.py,如下:

    from cms.app_base import CMSApp
    from cms.apphook_pool import apphook_pool
    from django.utils.translation import ugettext_lazy as _
    
    class MyApphook(CMSApp):
        name = _("My Apphook")
        urls = ["myapp.urls"]
    
    apphook_pool.register(MyApphook)
    

    官方文档查看这里:http://docs.django-cms.org/en/latest/extending_cms/app_integration.html#app-hooks

    加载逻辑,通过discover_apps的load('cms_app')来加载(前提是在settings.py中未定义 CMS_APPHOOKS):在所有的installed_app中,查找cms_app模块,并自动import_module

    2) 在setting.py中定义CMS_APPHOOKS

    APPHOOKS=(
    'yourmodule.you_object1','yourmodule.you_object2',...
    )
    

    这是从源码中分析的来的,如下:

    C:Python27Libsite-packagesdjango_cms-3.0.3-py2.7.eggcmsapphook_pool.py (45~57)

        def discover_apps(self):
            self.apphooks = get_cms_setting('APPHOOKS')
    
            if self.apphooks:
                for cls in iterload_objects(self.apphooks):
                    try:
                        self.register(cls, discovering_apps=True)
                    except AppAlreadyRegistered:
                        pass
    
            else:
                load('cms_app')
    
            self.discovered = True
    

    iterload_objects,是一个生成器,如下:

    def iterload_objects(import_paths):
        """
        Load a list of objects.
        """
        for import_path in import_paths:
            yield load_object(import_path)
    

    load_object

    def load_object(import_path):
        if '.' not in import_path:
            raise TypeError(
                "'import_path' argument to 'django_load.core.load_object' must "
                "contain at least one dot."
            )
        module_name, object_name = import_path.rsplit('.', 1)
        module = import_module(module_name)
        return getattr(module, object_name)
    

    顺便分析下 C:Python27Libsite-packagesdjango_cms-3.0.3-py2.7.eggcmsapphook_pool.py的源码:

     实例变量:

        def __init__(self):
            self.apphooks = []
            self.apps = {}
            self.discovered = False
    

    方法:clear/register/discover_apps/get_apphooks/get_apphook

    其中: discover_apps上面已经分析过了。

    clear,清空实例变量,如下(作者说,python不需要clear,会自动回收,这个方法该砍掉了):

        def clear(self):
            # TODO: remove this method, it's Python, we don't need it.
            self.apphooks = []
            self.apps = {}
            self.discovered = False
    

    register,用于注册app,app的基类如下:

    class CMSApp(object):
        name = None
        urls = None
        menus = []
        app_name = None
        permissions = True
    

    register,本质是把app放到apphook_pool实例的apps中,不过之前会有一些验证,如下:

        def register(self, app, discovering_apps=False):
            if self.apphooks and not discovering_apps:
                return
    
            if app.__name__ in self.apps:
                raise AppAlreadyRegistered(
                    'A CMS application %r is already registered' % app.__name__)
    
            if not issubclass(app, CMSApp):
                raise ImproperlyConfigured(
                    'CMS application must inherit from cms.app_base.CMSApp, '
                    'but %r does not' % app.__name__)
    
            if not hasattr(app, 'menus') and hasattr(app, 'menu'):
                warnings.warn("You define a 'menu' attribute on CMS application %r, "
                    "but the 'menus' attribute is empty, did you make a typo?" % app.__name__)
    
            self.apps[app.__name__] = app
    

    其干活的代码只有最后一句:

    self.apps[app.__name__] = app
    

    get_apphooks, 返回一个列表 [(app,app.name)....],并按照app.name排序,如下:

        def get_apphooks(self):
            hooks = []
    
            if not self.discovered:
                self.discover_apps()
    
            for app_name in self.apps:
                app = self.apps[app_name]
    
                if app.urls:
                    hooks.append((app_name, app.name))
    
            # Unfortunately, we loose the ordering since we now have a list of tuples. Let's reorder by app_name:
            hooks = sorted(hooks, key=lambda hook: hook[1])
    
            return hooks
    

    get_apphook,根据app名字查找app,代码如下:

        def get_apphook(self, app_name):
            if not self.discovered:
                self.discover_apps()
    
            try:
                return self.apps[app_name]
            except KeyError:
                # deprecated: return apphooks registered in db with urlconf name instead of apphook class name
                for app in self.apps.values():
                    if app_name in app.urls:
                        return app
    
            raise ImproperlyConfigured('No registered apphook %r found' % app_name)
    

      



     

  • 相关阅读:
    Word操作——通配符
    圆的拟合
    最优化案例整理
    机器学习数学基础知识备忘
    scikit-learn学习笔记
    Linux下安装scikit-learn
    ROS学习备忘
    [ROS]激光驱动安装
    CMake和Linux编程:find_package的使用
    [OpenCV]直线拟合
  • 原文地址:https://www.cnblogs.com/Tommy-Yu/p/3975330.html
Copyright © 2011-2022 走看看