282 def parent_classes(cls): |
282 def parent_classes(cls): |
283 parents = [cls.vreg.etype_class(e.type) for e in cls.e_schema.ancestors()] |
283 parents = [cls.vreg.etype_class(e.type) for e in cls.e_schema.ancestors()] |
284 parents.append(cls.vreg.etype_class('Any')) |
284 parents.append(cls.vreg.etype_class('Any')) |
285 return parents |
285 return parents |
286 |
286 |
|
287 @classmethod |
|
288 @cached |
|
289 def _rest_attr_info(cls): |
|
290 mainattr, needcheck = 'eid', True |
|
291 if cls.rest_attr: |
|
292 mainattr = cls.rest_attr |
|
293 needcheck = not cls.e_schema.has_unique_values(mainattr) |
|
294 else: |
|
295 for rschema in cls.e_schema.subject_relations(): |
|
296 if rschema.is_final() and rschema != 'eid' and cls.e_schema.has_unique_values(rschema): |
|
297 mainattr = str(rschema) |
|
298 needcheck = False |
|
299 break |
|
300 if mainattr == 'eid': |
|
301 needcheck = False |
|
302 return mainattr, needcheck |
|
303 |
287 def __init__(self, req, rset=None, row=None, col=0): |
304 def __init__(self, req, rset=None, row=None, col=0): |
288 AppRsetObject.__init__(self, req, rset, row, col) |
305 AppRsetObject.__init__(self, req, rset, row, col) |
289 dict.__init__(self) |
306 dict.__init__(self) |
290 self._related_cache = {} |
307 self._related_cache = {} |
291 if rset is not None: |
308 if rset is not None: |
361 # the object for use in the relation is tricky |
378 # the object for use in the relation is tricky |
362 # XXX search_state is web specific |
379 # XXX search_state is web specific |
363 if getattr(self.req, 'search_state', ('normal',))[0] == 'normal': |
380 if getattr(self.req, 'search_state', ('normal',))[0] == 'normal': |
364 kwargs['base_url'] = self.metainformation()['source'].get('base-url') |
381 kwargs['base_url'] = self.metainformation()['source'].get('base-url') |
365 if method is None or method == 'view': |
382 if method is None or method == 'view': |
366 kwargs['_restpath'] = self.rest_path() |
383 kwargs['_restpath'] = self.rest_path(kwargs.get('base_url')) |
367 else: |
384 else: |
368 kwargs['rql'] = 'Any X WHERE X eid %s' % self.eid |
385 kwargs['rql'] = 'Any X WHERE X eid %s' % self.eid |
369 return self.build_url(method, **kwargs) |
386 return self.build_url(method, **kwargs) |
370 |
387 |
371 def rest_path(self): |
388 def rest_path(self, use_ext_eid=False): |
372 """returns a REST-like (relative) path for this entity""" |
389 """returns a REST-like (relative) path for this entity""" |
373 mainattr, needcheck = self._rest_attr_info() |
390 mainattr, needcheck = self._rest_attr_info() |
374 etype = str(self.e_schema) |
391 etype = str(self.e_schema) |
375 if mainattr == 'eid': |
392 path = etype.lower() |
376 value = self.eid |
393 if mainattr != 'eid': |
377 else: |
|
378 value = getattr(self, mainattr) |
394 value = getattr(self, mainattr) |
379 if value is None: |
395 if value is None: |
380 return '%s/eid/%s' % (etype.lower(), self.eid) |
396 mainattr = 'eid' |
381 if needcheck: |
397 path += '/eid' |
382 # make sure url is not ambiguous |
398 elif needcheck: |
383 rql = 'Any COUNT(X) WHERE X is %s, X %s %%(value)s' % (etype, mainattr) |
399 # make sure url is not ambiguous |
384 if value is not None: |
400 rql = 'Any COUNT(X) WHERE X is %s, X %s %%(value)s' % ( |
385 nbresults = self.req.execute(rql, {'value' : value})[0][0] |
401 etype, mainattr) |
386 # may an assertion that nbresults is not 0 would be a good idea |
402 if value is not None: |
387 if nbresults != 1: # no ambiguity |
403 nbresults = self.req.execute(rql, {'value' : value})[0][0] |
388 return '%s/eid/%s' % (etype.lower(), self.eid) |
404 if nbresults != 1: # ambiguity? |
389 return '%s/%s' % (etype.lower(), self.req.url_quote(value)) |
405 mainattr = 'eid' |
390 |
406 path += '/eid' |
391 @classmethod |
|
392 def _rest_attr_info(cls): |
|
393 mainattr, needcheck = 'eid', True |
|
394 if cls.rest_attr: |
|
395 mainattr = cls.rest_attr |
|
396 needcheck = not cls.e_schema.has_unique_values(mainattr) |
|
397 else: |
|
398 for rschema in cls.e_schema.subject_relations(): |
|
399 if rschema.is_final() and rschema != 'eid' and cls.e_schema.has_unique_values(rschema): |
|
400 mainattr = str(rschema) |
|
401 needcheck = False |
|
402 break |
|
403 if mainattr == 'eid': |
407 if mainattr == 'eid': |
404 needcheck = False |
408 if use_ext_eid: |
405 return mainattr, needcheck |
409 value = self.metainformation()['extid'] |
|
410 else: |
|
411 value = self.eid |
|
412 return '%s/%s' % (path, self.req.url_quote(value)) |
406 |
413 |
407 def attr_metadata(self, attr, metadata): |
414 def attr_metadata(self, attr, metadata): |
408 """return a metadata for an attribute (None if unspecified)""" |
415 """return a metadata for an attribute (None if unspecified)""" |
409 value = getattr(self, '%s_%s' % (attr, metadata), None) |
416 value = getattr(self, '%s_%s' % (attr, metadata), None) |
410 if value is None and metadata == 'encoding': |
417 if value is None and metadata == 'encoding': |