def get_template_context(self, *args, **kwargs): ctxt = super().get_template_context(*args, **kwargs) activities = ctxt['page'].object_list CremeEntity.populate_relations(activities, self._RTYPES_2_POP) # Optimisation entity = ctxt.get('object') if entity is not None: for activity in activities: activity.enable_unlink_button = True if isinstance(entity, Organisation): # We display the 'unlink' button only for Activities that have # at least a Relation with the Organisation (if a direct Relation # does not exist the button is useless). for activity in activities: activity.enable_unlink_button = \ any(entity.id == rel.object_entity_id for rel in chain(activity.get_subject_relations(), activity.get_linkedto_relations(), ) ) ctxt['display_review'] = SettingValue.objects.get_4_key(review_key).value return ctxt
def detailview_display(self, context): graph = context['object'] btc = self.get_template_context(context, graph.roots.select_related('entity')) CremeEntity.populate_real_entities( [node.entity for node in btc['page'].object_list]) return self._render(btc)
def detailview_display(self, context): btc = self.get_template_context( context, SemiFixedRelationType.objects.all(), ) CremeEntity.populate_real_entities([sfrt.object_entity for sfrt in btc['page'].object_list]) return self._render(btc)
def restore(self): CremeEntity.restore(self) # TODO: in a signal handler instead ? # (we need a restore signal, or an official "backup" feature -- see HistoryLine) if self.status in (constants.MAIL_STATUS_NOTSENT, constants.MAIL_STATUS_SENDINGERROR): # TODO: regroup the 'refresh' message, to avoid flooding the job manager from ..creme_jobs import entity_emails_send_type entity_emails_send_type.refresh_job()
def detailview_display(self, context): btc = self.get_template_context( context, InstanceBrickConfigItem.objects.prefetch_related('entity'), ) CremeEntity.populate_real_entities( [ibci.entity for ibci in btc['page'].object_list]) return self._render(btc)
def detailview_display(self, context): btc = self.get_template_context( context, context['object'].get_mails().select_related('recipient_entity'), ) CremeEntity.populate_real_entities( [*filter(None, (lw_mail.recipient_entity for lw_mail in btc['page'].object_list))] ) return self._render(btc)
def restore(self): CremeEntity.restore(self) # TODO: in a signal handler instead ? # (we need a restore signal, or an official "backup" feature -- see HistoryLine) from .sending import EmailSending, SENDING_STATE_DONE if EmailSending.objects.filter(campaign=self).exclude( state=SENDING_STATE_DONE).exists(): # TODO: regroup the 'refresh' message, to avoid flooding the job manager from ..creme_jobs import campaign_emails_send_type campaign_emails_send_type.refresh_job()
def populate_entities(histories): # entities_pks = histories.values_list('entity_pk', flat=True) entities_pks = [history.entity_pk for history in histories] # entities = CremeEntity.objects.filter(pk__in=entities_pks) entities = CremeEntity.objects.filter( pk__in=set(entities_pks) ) #Forcing the retrieve for MySQL <= v5.1.49 which "doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery" CremeEntity.populate_real_entities(entities) entities_map = { entity.pk: entity.get_real_entity() for entity in entities } for hist in histories: hist._entity = entities_map.get(hist.entity_pk)
def test_actions_void01(self): "Instance actions" user = self.user registry = self.registry class MockA(MockAction): id = 'test-a' class MockB(MockContactAction): id = 'test-b' class MockC(MockAction): id = 'test-c' registry.register_instance_actions(MockA, MockB, MockC) registry.void_instance_actions(FakeOrganisation, MockC) entity = CremeEntity(user=user) contact = FakeContact(user=user, last_name='Kawa') orga = FakeOrganisation(user=user, name='Kimengumi') self.assertSortedActions([MockA, MockC], registry.instance_actions(user=user, instance=entity)) self.assertSortedActions([MockA, MockB, MockC], registry.instance_actions(user=user, instance=contact)) self.assertSortedActions([MockA], registry.instance_actions(user=user, instance=orga))
def test_override03(self): "Bulk action" user = self.user registry = self.registry registry.register_bulk_actions(MockBulkAction) registry.register_bulk_actions(MockContactBulkAction) self.assertFalse([ *registry.instance_actions(user=user, instance=CremeEntity(user=user)) ]) self.assertFalse([ *registry.instance_actions(user=user, instance=FakeContact(user=user)) ]) self.assertFalse([ *registry.instance_actions(user=user, instance=FakeOrganisation(user=user)) ]) self.assertSortedActions([MockBulkAction], registry.bulk_actions(user=user, model=CremeEntity)) self.assertSortedActions([MockContactBulkAction], registry.bulk_actions(user=user, model=FakeContact)) self.assertSortedActions([MockBulkAction], registry.bulk_actions(user=user, model=FakeOrganisation))
def test_action_is_registered_for_instance02(self): "One action registered" user = self.user registry = self.registry entity = CremeEntity(user=user) contact = FakeContact(user=user, first_name='Yui', last_name='Kawa') registry.register_instance_actions(MockAction) # Entity --- entity_actions = [ *registry.instance_actions(user=user, instance=entity) ] self.assertEqual(1, len(entity_actions)) entity_action = entity_actions[0] self.assertIsInstance(entity_action, MockAction) self.assertEqual(user, entity_action.user) self.assertEqual(CremeEntity, entity_action.model) self.assertEqual(entity, entity_action.instance) self.assertEqual([MockAction], registry.instance_action_classes(model=CremeEntity)) # Contact --- contact_actions = [ *registry.instance_actions(user=user, instance=contact) ] self.assertEqual(1, len(contact_actions)) contact_action = contact_actions[0] self.assertIsInstance(contact_action, MockAction) self.assertEqual(user, contact_action.user) self.assertEqual(FakeContact, contact_action.model) self.assertEqual(contact, contact_action.instance) self.assertEqual([MockAction], registry.instance_action_classes(model=FakeContact))
def test_override_duplicate(self): user = self.user registry = self.registry registry.register_instance_actions(MockAction) registry.register_instance_actions(MockContactAction) entity = CremeEntity(user=user) contact = FakeContact(user=user) self.assertSortedActions([MockAction], registry.instance_actions(user=user, instance=entity)) self.assertSortedActions([MockContactAction], registry.instance_actions(user=user, instance=contact)) # Same action, no problem registry.register_instance_actions(MockContactAction) self.assertSortedActions([MockAction], registry.instance_actions(user=user, instance=entity)) self.assertSortedActions([MockContactAction], registry.instance_actions(user=user, instance=contact)) # Other action, raise error --- class MockA(MockContactAction): pass with self.assertRaises(ActionRegistrationError) as ctxt: registry.register_instance_actions(MockA) self.assertEqual( str(ctxt.exception), "Duplicated action '{}' for model {}".format( MockA.id, MockContactAction.model))
def test_override01(self): "Empty." user = self.user registry = self.registry self.assertFalse([ *registry.instance_actions(user=user, instance=CremeEntity(user=user)) ]) self.assertFalse([ *registry.instance_actions(user=user, instance=FakeContact(user=user)) ]) self.assertFalse([ *registry.instance_actions(user=user, instance=FakeOrganisation(user=user)) ]) self.assertFalse( [*registry.bulk_actions(user=user, model=CremeEntity)]) self.assertFalse( [*registry.bulk_actions(user=user, model=FakeContact)]) self.assertFalse( [*registry.bulk_actions(user=user, model=FakeOrganisation)])
def generate_png(self, user): from os.path import join import pygraphviz as pgv # NB: to work with utf8 label in node: all node must be added explicitly with # unicode label, and when edges are a created, nodes identified by their # labels encoded as string graph = pgv.AGraph(directed=True) # NB: "self.roots.all()" causes a strange additional query (retrieving of the base CremeEntity !).... has_perm_to_view = user.has_perm_to_view roots = [ root for root in RootNode.objects.filter( graph=self.id).select_related('entity') if not root.entity.is_deleted and has_perm_to_view(root.entity) ] add_node = graph.add_node add_edge = graph.add_edge # TODO: entity cache ? regroups relations by type ? ... CremeEntity.populate_real_entities([root.entity for root in roots ]) #small optimisation for root in roots: add_node(str(root.entity), shape='box') # add_node('filled box', shape='box', style='filled', color='#FF00FF') # add_node('filled box v2', shape='box', style='filled', fillcolor='#FF0000', color='#0000FF', penwidth='2.0') #default pensize="1.0" orbital_nodes = {} #cache for root in roots: subject = root.entity str_subject = str(subject) relations = subject.relations.filter(type__in=root.relation_types.all())\ .select_related('object_entity', 'type') Relation.populate_real_object_entities( relations) # Small optimisation for relation in relations: object_ = relation.object_entity if not user.has_perm_to_view(object_): continue uni_object = str(object_) str_object = uni_object orbital_node = orbital_nodes.get(object_.id) if not orbital_node: add_node(uni_object) orbital_nodes[object_.id] = str_object add_edge(str_subject, str_object, label=str(relation.type.predicate)) # add_edge('b', 'd', color='#FF0000', fontcolor='#00FF00', label='foobar', style='dashed') orbital_rtypes = self.orbital_relation_types.all() if orbital_rtypes: orbital_ids = orbital_nodes.keys() for relation in Relation.objects.filter( subject_entity__in=orbital_ids, object_entity__in=orbital_ids, type__in=orbital_rtypes).select_related('type'): add_edge(orbital_nodes[relation.subject_entity_id], orbital_nodes[relation.object_entity_id], label=str(relation.type.predicate), style='dashed') # print graph.string() graph.layout(prog='dot') # Algo: neato dot twopi circo fdp nop img_format = 'png' # Format: pdf svg img_basename = 'graph_{}.{}'.format(self.id, img_format) try: path = FileCreator(join(settings.MEDIA_ROOT, 'upload', 'graphs'), img_basename).create() except FileCreator.Error as e: raise self.GraphException(e) from e try: # graph.draw(join(dir_path, filename), format='png') # Format: pdf svg graph.draw(path, format=img_format) # Format: pdf svg except IOError as e: delete_file(path) raise self.GraphException(str(e)) from e fileref = FileRef.objects.create( # user=request.user, TODO filedata='upload/graphs/' + basename(path), basename=img_basename, ) return HttpResponseRedirect( reverse('creme_core__dl_file', args=(fileref.filedata, )))
def test_is_date_field(self): entity = CremeEntity() get_field = entity._meta.get_field self.assertTrue(meta.is_date_field(get_field('created'))) self.assertFalse(meta.is_date_field(get_field('user')))