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:\Python27\Lib\site-packages\django_cms-3.0.3-py2.7.egg\cms\apphook_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:\Python27\Lib\site-packages\django_cms-3.0.3-py2.7.egg\cms\apphook_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)

  


 

django-cms 代码研究(八)app hooks的更多相关文章

  1. 手机自动化测试:Appium源码分析之跟踪代码分析八

    手机自动化测试:Appium源码分析之跟踪代码分析八   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家 ...

  2. django-cms 代码研究(一)djangocms是什么

    首先用djangocms生成了一个站点(具体参考这里:http://www.cnblogs.com/Tommy-Yu/p/3878488.html),其文件结构如下: 本来以为会很有逼格,结果一看傻眼 ...

  3. pycharm上运行django服务器端、以及创建app方法

     快来加入群[python爬虫交流群](群号570070796),发现精彩内容. 安装Django  下载Django包,解压缩. CMD 进入解压路径下. 执行:python setup.py in ...

  4. Django之代码风格

    1 代码风格 稍微关注一下下面这些代码标准风格指导规则将会对你大有益处,我们高度建议你通读词章,即便你此时可能正想跳过它. 1.1 让你的代码保持可读性的重要性 代码在读方面的重要性胜过写.一个代码块 ...

  5. 一段markdown编辑器代码研究

    一段markdown编辑器代码研究 说明 代码在 https://github.com/dukeofharen/markdown-editor 之所以选择这个来分析是一方面是因为它的代码结构比较简单, ...

  6. CWMP开源代码研究——git代码工程

    原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 声明:本系列涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅 ...

  7. dedecms代码研究二

    dedecms代码研究(2)从index开始现在继续,今天讲的主要是dedecms的入口代码.先打开index.PHP看看里面是什么吧.打开根目录下的index.php嗯映入眼帘的是一个if语句.检查 ...

  8. DEDECMS数据库执行原理、CMS代码层SQL注入防御思路

    我们在上一篇文章中学习了DEDECMS的模板标签.模板解析原理,以及通过对模板核心类的Hook Patch来对模板的解析流量的攻击模式检测,达到修复模板类代码执行漏洞的目的 http://www.cn ...

  9. Django中的Project和App的区别

    Django是一个非常流行的用python编写的Web框架,在使用Django之前,我们需要了解一些基本的概念,这样可以在使用Django的时候对其有一个更加深入的把握.本文主要介绍Django中两个 ...

  10. Ningx代码研究.

    概述 研究计划 参与人员 研究文档 学习emiller的文章 熟悉nginx的基本数据结构 nginx 代码的目录结构 nginx简单的数据类型的表示 nginx字符串的数据类型的表示 内存分配相关 ...

随机推荐

  1. AngularJS开发指南15:AngularJS的创建服务,将服务注入到控制器,管理服务依赖详解

    创建服务 虽然AngularJS提供了很多有用的服务,但是如果你要创建一个很棒的应用,你可能还是要写自己的服务.你可以通过在模块中注册一个服务工厂函数,或者通过Module#factory api或者 ...

  2. 读代码之private construtor

    private 构造函数 private修饰构造函数在Singleton设计模式中经常使用.但是今天在读到EntityUtils时,发现这是一个final类.final很好理解:EntityUtils ...

  3. Android Studio能干什么

    建立系统工具包可以用来生成,测试,运行您的应用程序和软件包.构建系统是独立于Android的工作室,所以你可以调用它的Android的工作室或从命令行.在你写你的应用程序,你可以使用编译系统的特点: ...

  4. python:open文件操作

    file: jim|123|1 tom|321|3 kamil|432|1 # __author__ = liukun # coding:utf-8 obj = open('file.txt','r' ...

  5. int方法

    代码 #int内部功能 name='Kamil.Liu' age=18 num=-11 print(dir(age)) print(age.bit_length())#返回表示当前数字占用的最少位数 ...

  6. JAVA TIMER定时器

    备注:类实现ServletContextListener,在web.xml配置,之后服务启动该定时器类自动加载 package com.leadlt.common.util; import java. ...

  7. request.getAttribute() 和 request.getParameter() 有何区别?

    HttpServletRequest类既有getAttribute()方法,也由getParameter()方法,这两个方法有以下区别: (1)HttpServletRequest类有setAttri ...

  8. 淘宝业务常用english

    ADX        ad exchange 广告交易平台 coupon     赠品 CPC         cost per click CPS         cost per sales CT ...

  9. POJ-2352 Stars 树状数组

    Stars Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 39186 Accepted: 17027 Description A ...

  10. POJ3749 破译密码

    Description 据说最早的密码来自于罗马的凯撒大帝.消息加密的办法是:对消息原文中的每个字母,分别用该字母之后的第5个字母替换(例如:消息原文中的每个字母A都分别替换成字母F).而你要获得消息 ...