controller.py :  » Network » Twisted » Twisted-1.0.3 » Twisted-1.0.3 » twisted » web » woven » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Twisted 
Twisted » Twisted 1.0.3 » Twisted 1.0.3 » twisted » web » woven » controller.py

# Twisted, the Framework of Your Internet
# Copyright (C) 2000-2002 Matthew W. Lefkowitz
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

from __future__ import nested_scopes

__version__ = "$Revision: 1.34 $"[11:-2]

import os
import cgi
import types

from twisted.python import log
from twisted.python import components
from twisted.web import resource,server,static
from twisted.web.woven import interfaces,utils
from twisted.web import woven
from twisted.web.static import redirectTo,addSlash

import warnings
from time import time

def controllerFactory(controllerClass):
    return lambda request, node, model: controllerClass(model)

def controllerMethod(controllerClass):
    return lambda self, request, node, model: controllerClass(model)


class Controller(resource.Resource):
    """
    A Controller which handles to events from the user. Such events
    are `web request', `form submit', etc.

    I should be the IResource implementor for your Models (and
    L{registerControllerForModel} makes this so).
    """

    __implements__ = (interfaces.IController, resource.IResource)
    setupStacks = 1
    controllerLibraries = []
    viewFactory = None
    templateDirectory = ""
    def __init__(self, m, inputhandlers=None, view=None, controllers=None, templateDirectory = None):
        #self.start = now()
        resource.Resource.__init__(self)
        self.model = m
        # It's the responsibility of the calling code to make sure setView is
        # called on this controller before it's rendered.
        self.view = None
        self.subcontrollers = []
        if self.setupStacks:
            self.setupControllerStack()
        if inputhandlers is None and controllers is None:
            self._inputhandlers = []
        elif inputhandlers:
            print "The inputhandlers arg is deprecated, please use controllers instead"
            self._inputhandlers = inputhandlers
        else:
            self._inputhandlers = controllers
        if templateDirectory is not None:
            self.templateDirectory = templateDirectory
        self._valid = {}
        self._invalid = {}
        self._process = {}
        self._parent = None

    def setupControllerStack(self):
        self.controllerStack = utils.Stack([])
        from twisted.web.woven import input
        if input not in self.controllerLibraries:
            self.controllerLibraries.append(input)
        for library in self.controllerLibraries:
            self.importControllerLibrary(library)
        self.controllerStack.push(self)
    
    def importControllerLibrary(self, namespace):
        if not hasattr(namespace, 'getSubcontroller'):
            namespace.getSubcontroller = utils.createGetFunction(namespace)
        self.controllerStack.push(namespace)

    def getSubcontroller(self, request, node, model, controllerName):
        controller = None
        cm = getattr(self, 'wcfactory_' +
                                    controllerName, None)
        if cm is None:
            cm = getattr(self, 'factory_' +
                                         controllerName, None)
            if cm is not None:
                warnings.warn("factory_ methods are deprecated; please use "
                              "wcfactory_ instead", DeprecationWarning)
        if cm:
            if cm.func_code.co_argcount == 1 and not type(vm) == types.LambdaType:
                warnings.warn("A Controller Factory takes "
                              "(request, node, model) "
                              "now instead of (model)", DeprecationWarning)
                controller = controllerFactory(model)
            else:
                controller = cm(request, node, model)
        return controller

    def setSubcontrollerFactory(self, name, factory, setup=None):
        setattr(self, "wcfactory_" + name, lambda request, node, m:
                                                    factory(m))

    def setView(self, view):
        self.view = view

    def setUp(self, request, *args):
        """
        @type request: L{twisted.web.server.Request}
        """
        pass

    def getChild(self, name, request):
        """
        Look for a factory method to create the object to handle the
        next segment of the URL. If a wchild_* method is found, it will
        be called to produce the Resource object to handle the next
        segment of the path.
        """
        if not name:
            method = "index"
        else:
            method = name
        f = getattr(self, "wchild_%s" % method, None)
        if f:
            return f(request)
        elif name == '':
            return self
        else:
            return resource.Resource.getChild(self, name, request)

    def render(self, request):
        """
        Trigger any inputhandlers that were passed in to this Page,
        then delegate to the View for traversing the DOM. Finally,
        call gatheredControllers to deal with any InputHandlers that
        were constructed from any controller= tags in the
        DOM. gatheredControllers will render the page to the browser
        when it is done.
        """
        # Handle any inputhandlers that were passed in to the controller first
        for ih in self._inputhandlers:
            ih._parent = self
            ih.handle(request)
        for key, value in self._valid.items():
            key.commit(request, None, value)
        self._valid = {}
        return self.renderView(request)

    def makeView(self, model, name, parentCount=0):
        v = self.viewFactory(model, name)
        v.parentCount = parentCount
        v.templateDirectory = self.templateDirectory
        v.tapestry = self
        v.importViewLibrary(self)
        return v

    def renderView(self, request):
        if self.view is None:
            if self.viewFactory is not None:
                self.setView(self.makeView(self.model, None))
            else:
                self.setView(components.getAdapter(self.model, interfaces.IView, None))
            self.view.setController(self)
        return self.view.render(request, doneCallback=self.gatheredControllers)

    def gatheredControllers(self, v, d, request):
        process = {}
        request.args = {}
        for key, value in self._valid.items():
            key.commit(request, None, value)
            process[key.submodel] = value
        self.process(request, **process)
        #log.msg("Sending page!")
        self.pageRenderComplete(request)
        utils.doSendPage(v, d, request)
        #v.unlinkViews()

        #print "Page time: ", now() - self.start
        #return view.View.render(self, request, block=0)

    def aggregateValid(self, request, input, data):
        self._valid[input] = data
        
    def aggregateInvalid(self, request, input, data):
        self._invalid[input] = data

    def process(self, request, **kwargs):
        if kwargs:
            log.msg("Processing results: ", kwargs)

    def setSubmodel(self, submodel):
        self.submodel = submodel

    def handle(self, request):
        """
        By default, we don't do anything
        """
        return (None, None)

    def domChanged(self, request, node):
        parent = getattr(self, 'parent', None)
        if parent is not None:
            parent.domChanged(request, node)

    def pageRenderComplete(self, request):
        """Override this to recieve notification when the view rendering
        process is complete.
        """
        pass

WOVEN_PATH = os.path.split(woven.__file__)[0]

class LiveController(Controller):
    """A Controller that encapsulates logic that makes it possible for this
    page to be "Live". A live page can have it's content updated after the
    page has been sent to the browser, and can translate client-side
    javascript events into server-side events.
    """
    def render(self, request):
        """First, check to see if this request is attempting to hook up the
        output conduit. If so, do it. Otherwise, unlink the current session's
        View from the MVC notification infrastructure, then render the page
        normally.
        """
        # Check to see if we're hooking up an output conduit
        sess = request.getSession(interfaces.IWovenLivePage)
        #print "REQUEST.ARGS", request.args
        if request.args.has_key('woven_hookupOutputConduitToThisFrame'):
            sess.hookupOutputConduit(request)
            return server.NOT_DONE_YET
        if request.args.has_key('woven_clientSideEventName'):
            eventName = request.args['woven_clientSideEventName'][0]
            eventTarget = request.args['woven_clientSideEventTarget'][0]
            eventArgs = request.args.get('woven_clientSideEventArguments', [])
            #print "EVENT", eventName, eventTarget, eventArgs
            self.view = sess.getCurrentPage()
            request.d = self.view.d
            target = self.view.subviews[eventTarget]
            target.onEvent(request, eventName, *eventArgs)
            sess.sendScript('woven_clientToServerEventComplete()')
            return '''<html>
    <body>
        %s event sent to %s with arguments %s.
    </body>
</html>''' % (eventName, cgi.escape(str(target)), eventArgs)

        # Unlink the current page in this user's session from MVC notifications
        page = sess.getCurrentPage()
        if page is not None:
            page.unlinkViews()
            sess.setCurrentPage(None)
        self.pageSession = None
        return Controller.render(self, request)

    def gatheredControllers(self, v, d, request):
        Controller.gatheredControllers(self, v, d, request)
        sess = request.getSession(interfaces.IWovenLivePage)
        #print "THIS PAGE IS GOING LIVE:", self
        self.pageSession = sess
        sess.setCurrentPage(self)

    def domChanged(self, request, node):
        print "DOM CHANGED"
        if self.pageSession is not None:
            nodeId = node.getAttribute('id')
            nodeXML = node.toxml()
            nodeXML = nodeXML.replace('\n', '')
            nodeXML = nodeXML.replace('\r', '')
            nodeXML = nodeXML.replace("'", "\\'")
            js = "top.woven_replaceElement('%s', '%s')" % (nodeId, nodeXML)
            self.pageSession.sendScript(js)

    def wchild_WebConduit2_js(self, request):
        print "returning js file"
        h = request.getHeader("user-agent")
        if h.count("MSIE"):
            fl = "WebConduit2_msie.js"
        else:
            fl = "WebConduit2_mozilla.js"

        return static.File(os.path.join(WOVEN_PATH, fl))

    def wchild_FlashConduit_swf(self, request):
        print "returning flash file"
        h = request.getHeader("user-agent")
        if h.count("MSIE"):
            fl = "FlashConduit.swf"
        else:
            fl = "FlashConduit.swf"
        return static.File(os.path.join(WOVEN_PATH, fl))

    def wchild_input_html(self, request):
        return BlankPage()


class BlankPage(resource.Resource):
    def render(self, request):
        return "<html>This space intentionally left blank</html>"


WController = Controller

def registerControllerForModel(controller, model):
    """
    Registers `controller' as an adapter of `model' for IController, and
    optionally registers it for IResource, if it implements it.

    @param controller: A class that implements L{interfaces.IController}, usually a
           L{Controller} subclass. Optionally it can implement
           L{resource.IResource}.
    @param model: Any class, but probably a L{twisted.web.woven.model.Model}
           subclass.
    """
    components.registerAdapter(controller, model, interfaces.IController)
    if components.implements(controller, resource.IResource):
        components.registerAdapter(controller, model, resource.IResource)

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.