Package gavo :: Package web :: Module qprenderer
[frames] | no frames]

Source Code for Module gavo.web.qprenderer

  1  """ 
  2  A renderer that queries a single field in a service. 
  3  """ 
  4   
  5  #c Copyright 2008-2019, the GAVO project 
  6  #c 
  7  #c This program is free software, covered by the GNU GPL.  See the 
  8  #c COPYING file in the source distribution. 
  9   
 10   
 11  from nevow import inevow 
 12  from nevow import rend 
 13  from nevow import tags as T 
 14  from twisted.internet import defer 
 15   
 16  from gavo import base 
 17  from gavo import svcs 
 18  from gavo.svcs import streaming 
 19  from gavo.web import common 
 20  from gavo.web import grend 
21 22 23 -class VOTableResource(rend.Page):
24 # A quick hack to support VOTable responses. 25 # Kill this in favour of serviceresults.
26 - def __init__(self, res):
27 rend.Page.__init__(self) 28 self.res = res
29
30 - def renderHTTP(self, ctx):
31 request = inevow.IRequest(ctx) 32 if base.getMetaText(self.res.getPrimaryTable(), "_queryStatus" 33 )=="OVERFLOW": 34 fName = "truncated_votable.xml" 35 else: 36 fName = "votable.xml" 37 request.setHeader("content-type", base.votableType) 38 request.setHeader('content-disposition', 39 'attachment; filename=%s'%fName) 40 return streaming.streamVOTable(request, self.res)
41
42 43 -class QPRenderer(grend.HTMLResultRenderMixin, 44 grend.CustomTemplateMixin, 45 grend.ServiceBasedPage):
46 """The Query Path renderer extracts a query argument from the query path. 47 48 Basically, whatever segments are left after the path to the renderer 49 are taken and fed into the service. The service must cooperate by 50 setting a queryField property which is the key the parameter is assigned 51 to. 52 53 QPRenderers cannot do forms, of course, but they can nicely share a 54 service with the form renderer. 55 56 To adjust the results' appreance, you can override resultline (for when 57 there's just one result row) and resulttable (for when there is more 58 than one result row) templates. 59 """ 60 name = "qp" 61 queryValue = None 62 63 @classmethod
64 - def isCacheable(self, segments, request):
65 return False # That's the default, but let's be sure here...
66
67 - def renderHTTP(self, ctx):
68 if not self.queryValue: 69 raise svcs.UnknownURI("This page is a root page for a" 70 " query-based service. You have to give a valid value in the" 71 " path.") 72 return self.runService( 73 {self.service.getProperty("queryField"): [self.queryValue]} 74 ).addCallback(self._formatOutput, ctx 75 ).addErrback(self._handleError, ctx)
76
77 - def _formatOutput(self, res, ctx):
78 if res.queryMeta["format"]=="VOTable": 79 # Hm... can we get rid of this hack? 80 return VOTableResource(res) 81 82 # Hm... I suppose this and the corresponding stuff in 83 # UnifiedDALRenderer should be merged. 84 if isinstance(res.original, tuple): 85 # core returned a complete document (mime and string) 86 request = inevow.IRequest(ctx) 87 mime, payload = res.original 88 request.setHeader("content-type", mime) 89 return streaming.streamOut(lambda f: f.write(payload), request) 90 91 nMatched = res.queryMeta.get("Matched", 0) 92 if nMatched==0: 93 raise svcs.UnknownURI("No record matching %s."%( 94 self.queryValue)) 95 elif nMatched==1: 96 self.customTemplate = self.getTemplate("resultline") 97 else: 98 self.customTemplate = self.getTemplate("resulttable") 99 self.result = res 100 return defer.maybeDeferred(super(QPRenderer, self).renderHTTP, ctx 101 ).addErrback(self._handleError, ctx)
102
103 - def _handleError(self, failure, ctx):
104 # all errors are translated to 404s 105 failure.printTraceback() 106 raise svcs.UnknownURI("The query initiated by your URL failed," 107 " yielding a message '%s'."%failure.getErrorMessage())
108
109 - def locateChild(self, ctx, segments):
110 # if we're here, we are the responsible resource and just stuff 111 # the remaining segments into the query value 112 self.queryValue = "/".join(segments) 113 return self, ()
114
115 - def getTemplate(self, resultFormat):
116 if resultFormat in self.service.templates: 117 return self.service.getTemplate(resultFormat) 118 return common.doctypedStan( 119 T.html[ 120 T.head(render=T.directive("commonhead"))[ 121 T.title(render=T.directive("meta"))['title'],], 122 T.body(render=T.directive("withsidebar"))[ 123 T.h1(render=T.directive("meta"))['title'], 124 T.div(class_="result", data=T.directive("result")) [ 125 T.invisible(render=T.directive(resultFormat))]]])
126