Commit 7dcc03a5 authored by Aurelien Campeas's avatar Aurelien Campeas
Browse files

[entity] Entity.related(): add a targettypes argument (closes #2957313)

This allows to restrict the entity types returned by the method
(passed to cw_related_rql).

When such an argument is given, no caching happens.
parent 4b3e657d17ab
......@@ -969,7 +969,7 @@ class Entity(AppObject):
return value
def related(self, rtype, role='subject', limit=None, entities=False, # XXX .cw_related
safe=False, targettypes=None):
"""returns a resultset of related entities
:param rtype:
......@@ -983,10 +983,13 @@ class Entity(AppObject):
:param safe:
if True, an empty rset/list of entities will be returned in case of
:exc:`Unauthorized`, else (the default), the exception is propagated
:param targettypes:
a tuple of target entity types to restrict the query
rtype = str(rtype)
if limit is None:
# we cannot do much wrt cache on limited queries
# Caching restricted/limited results is best avoided.
cacheable = limit is None and targettypes is None
if cacheable:
cache_key = '%s_%s' % (rtype, role)
if cache_key in self._cw_related_cache:
return self._cw_related_cache[cache_key][entities]
......@@ -994,7 +997,7 @@ class Entity(AppObject):
if entities:
return []
return self._cw.empty_rset()
rql = self.cw_related_rql(rtype, role, limit=limit)
rql = self.cw_related_rql(rtype, role, limit=limit, targettypes=targettypes)
rset = self._cw.execute(rql, {'x': self.eid})
except Unauthorized:
......@@ -1002,9 +1005,9 @@ class Entity(AppObject):
rset = self._cw.empty_rset()
if entities:
if limit is None:
if cacheable:
self.cw_set_relation_cache(rtype, role, rset)
return self.related(rtype, role, limit, entities)
return self.related(rtype, role, entities=entities)
return list(rset.entities())
return rset
......@@ -41,7 +41,7 @@ class Personne(EntityType):
constraints=[RQLConstraint('NOT EXISTS(O contrat_exclusif S)')])
dirige = SubjectRelation('Societe', cardinality='??',
constraints=[RQLConstraint('S actionnaire O')])
associe = SubjectRelation('Personne', cardinality='1*',
associe = SubjectRelation('Personne', cardinality='?*',
constraints=[RQLConstraint('S actionnaire SOC, O actionnaire SOC')])
class Ami(EntityType):
# -*- coding: utf-8 -*-
# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact --
# This file is part of CubicWeb.
......@@ -132,6 +132,12 @@ class EntityTC(CubicWebTC):
self.assertEqual(sorted(user._cw_related_cache), ['in_group_subject', 'primary_email_subject'])
for group in groups:
self.assertFalse('in_group_subject' in group._cw_related_cache, list(group._cw_related_cache))
user.related('in_group', entities=True)
self.assertIn('in_group_subject', user._cw_related_cache)
user.related('in_group', targettypes=('CWGroup',), entities=True)
self.assertNotIn('in_group_subject', user._cw_related_cache)
def test_related_limit(self):
req = self.request()
......@@ -145,6 +151,18 @@ class EntityTC(CubicWebTC):
self.assertEqual(len(p.related('tags', 'object', entities=True, limit=2)), 2)
self.assertEqual(len(p.related('tags', 'object', entities=True)), 4)
def test_related_targettypes(self):
req = self.request()
p = req.create_entity('Personne', nom=u'Loxodonta', prenom=u'Babar')
n = req.create_entity('Note', type=u'scratch', ecrit_par=p)
t = req.create_entity('Tag', name=u'a tag', tags=(p, n))
req = self.request()
t = req.entity_from_eid(t.eid)
self.assertEqual(2, t.related('tags').rowcount)
self.assertEqual(1, t.related('tags', targettypes=('Personne',)).rowcount)
self.assertEqual(1, t.related('tags', targettypes=('Note',)).rowcount)
def test_cw_instantiate_relation(self):
req = self.request()
p1 = req.create_entity('Personne', nom=u'di')
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment