source: MILK/trunk/milk_server/milk_server/models/DiscoveryState.py @ 5305

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/MILK/trunk/milk_server/milk_server/models/DiscoveryState.py@5305
Revision 5305, 6.9 KB checked in by cbyrom, 10 years ago (diff)

Improve structure of DiscoveryState? module by adding a new object,
PagerState? to hold the data connected to the results table paging.
Also tidy up code layout and simplify logic. Create new template
method, pagerControl, to represent the results table paging control

  • to allow reuse across the results and short_results templates.
Line 
1from paste.request import parse_querystring
2from milk_server.lib.Utilities import getURLConstraints
3import cgi,urllib
4
5   
6def getURLFormattedConstraints(environ, **kw):
7    '''
8    Get the constraints in a url friendly string - modified by the keyword arguments
9    offset and stride which are to be part of the querystring
10    @param environ: wsgi environ object
11    @return constraints in a url friendly string
12    '''
13    args = dict(parse_querystring(environ))
14
15    constrained = kw.get('constrained')
16    if not constrained:
17        offset, stride = kw.get('offset'), kw.get('stride')
18        if offset:
19            args['start'] = offset
20        if stride:
21            args['howmany'] = stride
22
23    q = ''
24    for i in args:
25        # NB, the constraints may already be encoded as a hidden variable
26        if i != 'constraints':
27            q+='%s=%s&'%(i,args[i])
28
29    # add constraints last to avoid duplicate params - NB, constraint params
30    # can be overridden by direct inputs to the page
31    if 'constraints' in args:
32        constraints = getURLConstraints(args['constraints'])
33        for key, val in constraints.items():
34            if key not in args:
35                q+='%s=%s&'%(key, val)
36
37    return q[0:-1]
38
39
40def getURL(environ, **kw):
41    '''
42    Get a url from the wsgi environment
43    @param environ: wsgi environ object
44    @return url with constraints added from wsgi environ
45    '''
46    constraints = getURLFormattedConstraints(environ, **kw)
47    return urllib.quote(environ.get('SCRIPT_NAME','')) + \
48        urllib.quote(environ.get('PATH_INFO','')) + '?' + constraints
49
50
51class constraints:
52    '''
53    A container object for constraints on a search
54    '''
55    def __init__(self, **kw):
56        self.values={}
57        keys=['dateRange','bbox','scope','textTarget','searchString','geoSearchType']
58        for key in keys:
59            self.values[key]=None
60        for k in kw: 
61            self[k]=kw[k]
62           
63           
64    def __setitem__(self, key, value):
65        if key in self.values:
66            self.values[key]=value
67        else:
68            raise ValueError('Unknown key [%s] in constraints')
69
70   
71    def __getitem__(self,key):
72        if key in self.values: 
73            return self.values[key]
74        else:
75            raise ValueError('Unknown key [%s] in constraints'%key)
76
77   
78    def __str__(self):
79        c=''
80        if self.values['dateRange'] is not None:
81            dr = self.values['dateRange'] 
82            c += 'Date range: %s to %s'%('%s/%s/%s'%dr[0],'%s/%s/%s'%dr[1])
83        bbox=self.values['bbox']
84        if c:
85            c += ', '
86        c += 'Bounding box: '
87        if bbox is None or bbox==['90.0','-180.0','180.0','-90.0']:
88            c+='Global'
89        else:
90            overlaps = self.values['geoSearchType'] or 'overlaps'
91            c+='%s latitude %s to %sN and longitude %s to %sE' \
92                %(overlaps,bbox[3],bbox[0],bbox[1],bbox[2])
93        if self.values['scope']: 
94            c += 'Scope: %s'%self.values['scope']
95        if self.values['textTarget']:
96            c += 'Target: %s'%self.values['textTarget']
97        return c
98
99
100class PagerState:
101    '''
102    Object to hold the current page state of the displayed results - e.g. which
103    page number and how many records, before and after those displayed, are available
104    '''
105   
106    def __init__(self, hits, environ, offset=1, stride=10):
107        '''
108        Initialise PagerState object
109        @param hits: total number of records available to view
110        @param environ: wsgi environ object   
111        @keyword offset: offset being used in the currently displayed record set
112        - i.e. the array number of the topmost record displayed. Default = 1
113        @keyword stride: Number of records currently visible.  Default = 10
114        '''
115        self.hits = hits
116        self.offset = offset
117        self.stride = stride
118
119        self.previousPageURL = None
120        self.previousNumber = None
121        self.startPageURL = None
122        self.nextPageURL = None
123        self.nextNumber = None
124        self.lastPageURL = None
125       
126        n, p = self.getNext()
127        start, end = "", ""
128        if p:
129            self.previousPageURL = getURL(environ, offset = p[0], stride = p[1])
130            self.previousNumber = p[1]
131            self.startPageURL = getURL(environ, offset = 1)
132        if n:
133            self.nextPageURL = getURL(environ, offset = n[0], stride = n[1])
134            self.nextNumber = n[1]
135            off = self.hits - 10
136            if off < 0:
137                off = 0
138            self.lastPageURL = getURL(environ, offset = off)
139           
140        self.upperRange = self.offset + self.stride - 1
141        self.lowerRange = self.offset
142       
143   
144    def getNext(self):
145        '''
146        Get info on what number of records are available on current page
147        @return result - list with format [[offSetForNextPage, numberOfRecordsOnNextPage],
148                                           [offSetForLastPage, numberOfRecordsOnLastPage]]
149        '''
150        result=[]
151        defStride=10
152        if self.offset+self.stride < self.hits:
153            #there are more to look at
154            r = [self.offset+self.stride, self.stride]
155            if r[0]+r[1]-1 > self.hits: 
156                r[1] = self.hits+1-r[0]
157            result.append(r)
158        else:
159            result.append([])
160           
161        if self.offset > 1:
162            #there are previous records
163            b = max(self.stride, defStride)
164            r = [self.offset-b,b]
165            if r[0] < 1: 
166                r[0] = 1
167            if r[1] > self.hits: 
168                r[1] = self.hits
169            result.append(r)
170        else: 
171            result.append([])
172        return result
173       
174   
175
176class DiscoveryState:
177    ''' This class holds the state associated with a search (including presenting multiple slices
178    of a large result set) '''
179    def __init__(self,sessionID,searchString,environ,hits,constraints,offset=1,stride=10):
180        ''' On instantiation, provide
181                the backend sessionID
182                the application URL that produced this query
183                the stride through the result set '''
184        self.environ=environ # the wsgi environment
185        self.constraintsInstance=constraints
186        self.constraints=str(constraints) # some text to show constraints on search
187        self.urlformattedconstraints = getURLFormattedConstraints(self.environ)
188        self.sessID=sessionID
189        self.hits=hits
190
191        self.searchString=searchString
192        self.alternatives=None
193        self.constrainedurl = getURL(self.environ, constrained=1)+'&constrained'
194        self.pager = PagerState(hits, self.environ, offset=offset, stride=stride)
195       
196    def __str__(self):
197        return '''
198___ Discovery State ___
199searchString: %s
200constraints: %s
201sessionID: %s
202hits: %s
203offset,stride: %s,%s
204environment: %s
205========================
206'''%(self.searchString,self.constraints,self.sessID,self.hits,self.offset,self.stride,self.environ)
Note: See TracBrowser for help on using the repository browser.