source: MILK/trunk/milk_server/milk_server/controllers/home.py @ 5234

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/MILK/trunk/milk_server/milk_server/controllers/home.py@5234
Revision 5234, 4.9 KB checked in by cbyrom, 11 years ago (diff)

Use htmlfill error rendering to simplify templates for atom create +
fix routes reference in tests + fix typo.

Line 
1'''
2 Base controller for MILK controllers, providing common functionality - including
3 fall back index method, to render a home page for the service depending on what
4 mode it is running in - NB, if multiple modes are enabled, the order of preference,
5 from highest to lowest, is editor, discovery, browser
6 
7 @author: C Byrom, Tessella Apr 2009
8'''
9import logging, traceback, xmlrpclib
10from formencode import htmlfill
11from milk_server.lib.base import *
12from ndg.common.src.lib.utilities import escapeSpecialCharacters
13from ndg.common.src.models.vocabtermdata import VocabTermData as VTD
14
15class HomeController(BaseController):
16    '''
17    Sets up appropriate home page for fall through urls
18    '''
19    def index(self):
20        '''
21        Redirect to the appropriate home page - or display error
22        '''
23        if g.atomEditorEnabled:
24            h.redirect_to(h.url_for('atomHome'))
25        elif g.discoveryEnabled:
26            h.redirect_to(h.url_for('discovery'))
27        elif g.browseEnabled:
28            h.redirect_to(h.url_for('browseHome'))
29        else:
30            c.title = "No service enabled"
31            c.xml = "The server should be configured to provide one or more of the followings client services: editor, discovery or browse."
32            return render("genshi", 'error')
33           
34
35    def savePageAndRender(self, template, **inputs):
36        '''
37        Save the current path info - to provide a memory function when changing
38        tabs + render the given template with the specified inputs filled in
39        automatically
40        @param template: name of template to render
41        @param inputs: dict of inputs with keynames matching input names in template
42        form 
43        '''
44        logging.debug("Saving current page url (%s) - to keep track of atom editor state" \
45                      %self.pathInfo)
46        session['currentEditor'] = self.pathInfo
47        session.save()
48        logging.debug("Now rendering current template (%s)" %template)
49        try:
50            html = render("genshi", template)
51            # replace any browse links with to links to editor
52            html = html.replace(VTD.BROWSE_SERVER_URL, g.server)
53           
54            # NB, need html in unicode for for htmlfill.render
55            html = unicode(html, 'utf-8', 'xmlcharrefreplace')
56            for key, val in inputs.items():
57                inputs[key] = str(val)
58   
59            return htmlfill.render(html, inputs, errors = c.errors)
60
61        except Exception, e:
62            c.xml = 'Unexpected error [%s] whilst rendering page' %str(e)
63            if str(e).find('malformed start tag') >-1:
64                c.xml += " - NB, this is probably due to illegal HTML being entered"
65            c.doc = ''
66            response.status_code = 400
67            logging.error(c.xml)
68            return render('error')
69
70
71    def _unpackErrors(self, e):
72        '''
73        Add exception errors to the common error structures - for use
74        in templates
75        @param e: Exception to add
76        @return errors: dict of errors
77        '''
78        if not c.errors:
79            c.errors = {}
80
81        errorMessage = e.message
82        if g.debugModeOn == 'True':
83            errorMessage = traceback.format_exc()
84
85        c.xml = escapeSpecialCharacters('Unexpected error loading page [%s]' \
86                                        %str(errorMessage))
87        c.doc = ''
88       
89        # unpack errors, if possible - NB, the c.errors value is used by the template
90        # function, displayErrors, which is used by most of the editor templates
91        if isinstance(e, xmlrpclib.Fault):
92            # strip out the exception type - NB, this is usually native library code
93            # and is of no real interest - and will just confuse viewers
94            c.errors['Unexpected error'] = e.faultString.split(':')[-1] 
95
96        if hasattr(e, 'unpack_errors'):
97            c.errors.update(e.unpack_errors())
98           
99        else:
100            c.errors['Unexpected error'] = [c.xml]
101
102        # tidy up errors - escaping any xml tags, if necessary
103        for key, errors in c.errors.items():
104            newErrors = []
105            for error in errors:
106                for err in error.split('<br/>'):
107                    newErrors.append(escapeSpecialCharacters(err))
108            c.errors[key] = newErrors
109       
110        return c.errors
111
112
113    def _handleError(self, e, template='error'):
114        '''
115        Handle exceptions thrown; if debug mode on, display full stack trace
116        in output, otherwise just show basic error message in error template
117        @param e: Exception to process
118        @keyword template: template to render - 'error' is the default - NB, if
119        an alternative is specified it should have a div with class set to 'error'
120        containing the variable, c.xml to display properly
121        '''
122        self._unpackErrors(e)
123        logging.error(c.xml)
124        response.status_code = 400
125        return render("genshi", template)
Note: See TracBrowser for help on using the repository browser.