Записки программиста, обо всем и ни о чем. Но, наверное, больше профессионального.

2015-03-15

Naudoc/Zope 2.10 Skins

Раньше
я показал, как сваять заготовку для Zope product (учтите, Zope 2.10!).
Теперь покажу, как кастомизировать скин Наудок/Zope. Ну, или просто добавить в пакет свой скин.

При кастомизации имеющегося файла самое сложное – найти этот файл. Тут надо умело объединить навыки поиска текста в файлах, анализа кода веб-страниц, понимания – откуда веб-страница взялась, знание устройства Zope CMF и прочие полезные скиллы.
Допустим, так или иначе, где-то в недрах папок «skins» нужный файл найден. И даже кастомизирован через инструмент ZMI — site — portal_skins Zope. Теперь самое время убрать из папки ZODB custom старую версию и сделать кастомизацию по взрослому. Через пакет Python.

В пакете сделаем папочку
MyPackege/skins/naucustom
и в нее положим найденный файл. Отредактировав его как требуется.

Осталась мелочь, зарегистрировать свой скин в portal_skins, так, чтобы наш слой оказался выше оригинального, но ниже спецслоя «custom».

Я это сделал так:
# MyPackage/skin.py
import os
import string
import types
import logging

from App.Common import package_home
from OFS.Image import manage_addImage
from Products.CMFCore.utils import getToolByName
import Products.CMFCore.DirectoryView as cmf_dv
from Products.CMFNauTools.Utils import joinpath, minimalpath
import Products.CMFNauTools.Exceptions as nau_errs

skin_layers = ('naucustom',)

def registerDirectory():
    cmf_dv.registerDirectory('skins', globals())
    for lyr in skin_layers:
        cmf_dv.registerDirectory('skins/%s' % lyr, globals())

class SkinsInstaller:
    def install(self, portal):
        self.site = portal
        ps = getToolByName(portal, 'portal_skins')
        self.portal_skins = ps
        for lyr in skin_layers:
            self.addSkinLayer(
                'bgpackage_%s' % lyr,
                'skins/%s' % lyr,
                globals(),
                after='custom'
            )

    def addSkinLayer(self, id, path, namespace=None, skin=None, before=None, after=None):
        ps = self.portal_skins
        if hasattr(ps, id):
            ps.manage_delObjects([id])

        # ensure the path is absolute
        if not os.path.isabs(path):
            if namespace is None:
                namespace = globals()
            package_path = minimalpath(package_home(namespace))
            path = joinpath(package_path, path)

        # createDirectoryView
        try:
            cmf_dv.createDirectoryView(ps, path, id)
        except nau_errs.DuplicateIdError:
            #~ This identifier is already in use
            log('SkinsInstaller.addSkinLayer: createDirectoryView failed, %s exists already' % id)

        # normalize parameters
        if not skin:
            skin = ps.getDefaultSkin()
        skin_path = ps.getSkinPath(skin)
        paths = map(string.strip, skin_path.split(','))
        if id in paths:
            # remove id from layers list
            clean_paths = [x for x in paths if x != id]
            paths = clean_paths

        # calculate layer place
        if before is after is None:
            place = len(paths)
        elif after is None:
            # before is not None
            if type(before) is types.ListType:
                places = [paths.index(bef) for bef in before]
                places.sort()
                place = places[0]
            else:
                place = paths.index(before) # may raise IndexError
        elif before is None:
            # after is not None
            place = paths.index(after) + 1 # may raise IndexError
        else:
            raise SimpleError("'before' or|and 'after' must be None")

        # add layer to list
        paths.insert(place, id)
        ps.addSkinSelection(skin, ','.join(paths))


# MyPackage/__init__.py
import os
import string
import types
import logging
from App.Common import package_home
from OFS.Image import manage_addImage
from Products.CMFCore.utils import getToolByName
import Products.CMFCore.DirectoryView as cmf_dv
from Products.CMFNauTools.Utils import joinpath, minimalpath
import Products.CMFNauTools.Exceptions as nau_errs

import skin

def getZopeApp(product_context):
    """Return Zope2 Application from ProductContext
    http://product-developers.narkive.com/mJghBKT8/grabbing-app-root-in-product-initialization
    """
    bobo_application = None
    try:
        from Zope2 import bobo_application
    except ImportError:
        log("can't import bobo_application")
    if bobo_application is not None:
        app = bobo_application()
    else:
        app = product_context._ProductContext__app
    return app

def initialize(context):
    app = getZopeApp(context)
    si = skin.SkinsInstaller()
    si.install(app.docs)

skin.registerDirectory()

Болдом выделено главное.


Чуть не забыл, хотя я и использовал куски кода и модули Наудок, для лаконичности, можно скины добавить и без них, кусков из Наудок.



original post http://vasnake.blogspot.com/2015/03/naudoczope-210-skins.html

Комментариев нет:

Отправить комментарий

Архив блога

Ярлыки

linux (241) python (191) citation (186) web-develop (170) gov.ru (159) video (124) бытовуха (115) sysadm (100) GIS (97) Zope(Plone) (88) бурчалки (84) Book (83) programming (82) грабли (77) Fun (76) development (73) windsurfing (72) Microsoft (64) hiload (62) internet provider (57) opensource (57) security (57) опыт (55) movie (52) Wisdom (51) ML (47) driving (45) hardware (45) language (45) money (42) JS (41) curse (40) bigdata (39) DBMS (38) ArcGIS (34) history (31) PDA (30) howto (30) holyday (29) Google (27) Oracle (27) tourism (27) virtbox (27) health (26) vacation (24) AI (23) Autodesk (23) SQL (23) humor (23) Java (22) knowledge (22) translate (20) CSS (19) cheatsheet (19) hack (19) Apache (16) Klaipeda (15) Manager (15) web-browser (15) Никонов (15) functional programming (14) happiness (14) music (14) todo (14) PHP (13) course (13) scala (13) weapon (13) HTTP. Apache (12) SSH (12) frameworks (12) hero (12) im (12) settings (12) HTML (11) SciTE (11) USA (11) crypto (11) game (11) map (11) HTTPD (9) ODF (9) Photo (9) купи/продай (9) benchmark (8) documentation (8) 3D (7) CS (7) DNS (7) NoSQL (7) cloud (7) django (7) gun (7) matroska (7) telephony (7) Microsoft Office (6) VCS (6) bluetooth (6) pidgin (6) proxy (6) Donald Knuth (5) ETL (5) NVIDIA (5) Palanga (5) REST (5) bash (5) flash (5) keyboard (5) price (5) samba (5) CGI (4) LISP (4) RoR (4) cache (4) car (4) display (4) holywar (4) nginx (4) pistol (4) spark (4) xml (4) Лебедев (4) IDE (3) IE8 (3) J2EE (3) NTFS (3) RDP (3) holiday (3) mount (3) Гоблин (3) кухня (3) урюк (3) AMQP (2) ERP (2) IE7 (2) NAS (2) Naudoc (2) PDF (2) address (2) air (2) british (2) coffee (2) fitness (2) font (2) ftp (2) fuckup (2) messaging (2) notify (2) sharepoint (2) ssl/tls (2) stardict (2) tests (2) tunnel (2) udev (2) APT (1) Baltic (1) CRUD (1) Canyonlands (1) Cyprus (1) DVDShrink (1) Jabber (1) K9Copy (1) Matlab (1) Portugal (1) VBA (1) WD My Book (1) autoit (1) bike (1) cannabis (1) chat (1) concurrent (1) dbf (1) ext4 (1) idioten (1) join (1) krusader (1) license (1) life (1) migration (1) mindmap (1) navitel (1) pneumatic weapon (1) quiz (1) regexp (1) robot (1) science (1) seaside (1) serialization (1) shore (1) spatial (1) tie (1) vim (1) Науру (1) крысы (1) налоги (1) пианино (1)