967 else: |
967 else: |
968 self.cw_attr_cache[name] = value = None |
968 self.cw_attr_cache[name] = value = None |
969 return value |
969 return value |
970 |
970 |
971 def related(self, rtype, role='subject', limit=None, entities=False, # XXX .cw_related |
971 def related(self, rtype, role='subject', limit=None, entities=False, # XXX .cw_related |
972 safe=False): |
972 safe=False, targettypes=None): |
973 """returns a resultset of related entities |
973 """returns a resultset of related entities |
974 |
974 |
975 :param rtype: |
975 :param rtype: |
976 the name of the relation, aka relation type |
976 the name of the relation, aka relation type |
977 :param role: |
977 :param role: |
981 :param entities: |
981 :param entities: |
982 if True, the entites are returned; if False, a result set is returned |
982 if True, the entites are returned; if False, a result set is returned |
983 :param safe: |
983 :param safe: |
984 if True, an empty rset/list of entities will be returned in case of |
984 if True, an empty rset/list of entities will be returned in case of |
985 :exc:`Unauthorized`, else (the default), the exception is propagated |
985 :exc:`Unauthorized`, else (the default), the exception is propagated |
|
986 :param targettypes: |
|
987 a tuple of target entity types to restrict the query |
986 """ |
988 """ |
987 rtype = str(rtype) |
989 rtype = str(rtype) |
988 if limit is None: |
990 # Caching restricted/limited results is best avoided. |
989 # we cannot do much wrt cache on limited queries |
991 cacheable = limit is None and targettypes is None |
|
992 if cacheable: |
990 cache_key = '%s_%s' % (rtype, role) |
993 cache_key = '%s_%s' % (rtype, role) |
991 if cache_key in self._cw_related_cache: |
994 if cache_key in self._cw_related_cache: |
992 return self._cw_related_cache[cache_key][entities] |
995 return self._cw_related_cache[cache_key][entities] |
993 if not self.has_eid(): |
996 if not self.has_eid(): |
994 if entities: |
997 if entities: |
995 return [] |
998 return [] |
996 return self._cw.empty_rset() |
999 return self._cw.empty_rset() |
997 rql = self.cw_related_rql(rtype, role, limit=limit) |
1000 rql = self.cw_related_rql(rtype, role, limit=limit, targettypes=targettypes) |
998 try: |
1001 try: |
999 rset = self._cw.execute(rql, {'x': self.eid}) |
1002 rset = self._cw.execute(rql, {'x': self.eid}) |
1000 except Unauthorized: |
1003 except Unauthorized: |
1001 if not safe: |
1004 if not safe: |
1002 raise |
1005 raise |
1003 rset = self._cw.empty_rset() |
1006 rset = self._cw.empty_rset() |
1004 if entities: |
1007 if entities: |
1005 if limit is None: |
1008 if cacheable: |
1006 self.cw_set_relation_cache(rtype, role, rset) |
1009 self.cw_set_relation_cache(rtype, role, rset) |
1007 return self.related(rtype, role, limit, entities) |
1010 return self.related(rtype, role, entities=entities) |
1008 return list(rset.entities()) |
1011 return list(rset.entities()) |
1009 else: |
1012 else: |
1010 return rset |
1013 return rset |
1011 |
1014 |
1012 def cw_related_rql(self, rtype, role='subject', targettypes=None, limit=None): |
1015 def cw_related_rql(self, rtype, role='subject', targettypes=None, limit=None): |