def test_implicit_apply_distinct(self): f1 = DataField.objects.get_by_natural_key('tests', 'office', 'location') f2 = DataField.objects.get_by_natural_key('tests', 'title', 'name') c = DataConcept() c.save() DataConceptField(concept=c, field=f1).save() DataConceptField(concept=c, field=f2).save() # Due to the use of distinct, the concept fields appear in the SELECT # statement at this point. This is not a bug, but a requirement of SQL. # These columns are stripped downstream by the exporter. node = parsers.dataview.parse([{ 'concept': c.pk, 'sort': 'desc', 'visible': False, }], tree=Employee) self.assertEqual( unicode(node.apply(Employee.objects.distinct()).query) .replace(' ', ''), 'SELECT DISTINCT "tests_employee"."id", ' '"tests_office"."location", "tests_title"."name" FROM ' '"tests_employee" INNER JOIN "tests_office" ON ' '("tests_employee"."office_id" = "tests_office"."id") LEFT OUTER ' 'JOIN "tests_title" ON ("tests_employee"."title_id" = ' '"tests_title"."id") ORDER BY "tests_office"."location" DESC, ' '"tests_title"."name" DESC' .replace(' ', ''))
def test_field_for_concept(self): f = DataField.objects.get(model_name='title', field_name='name') c1 = DataConcept() c2 = DataConcept() c1.save() c2.save() cf = DataConceptField(concept=c1, field=f) cf.save() attrs = { 'concept': c1.pk, 'field': f.pk, 'operator': 'exact', 'value': 'CEO', 'cleaned_value': {'value': 'CEO', 'label': 'CEO'}, 'language': 'Name is CEO' } self.assertEqual( parsers.datacontext.validate(deepcopy(attrs), tree=Employee), attrs) # Invalid concept attrs = parsers.datacontext.validate({ 'concept': c2.pk, 'field': f.pk, 'operator': 'exact', 'value': 'CEO', }, tree=Employee) self.assertFalse(attrs['enabled'])
def test_published(self): concept = DataConcept(published=True) concept.save() DataConceptField(concept=concept, field=self.is_manager).save() DataConceptField(concept=concept, field=self.salary).save() self.assertEqual([x.pk for x in DataConcept.objects.published()], []) self.is_manager.published = True self.is_manager.save() self.salary.published = True self.salary.save() # Now published, it will appear self.assertEqual([x.pk for x in DataConcept.objects.published()], [concept.pk]) # Set the category to be an unpublished category and it should no # longer appear. concept.category = self.category concept.save() self.assertEqual([x.pk for x in DataConcept.objects.published()], []) # Publish the category and the concept should appear again self.category.published = True self.category.save() self.assertEqual([x.pk for x in DataConcept.objects.published()], [concept.pk]) user1 = User.objects.create_user('user1', 'user1') # Nothing since user1 cannot view either datafield self.assertEqual([x.pk for x in DataConcept.objects.published(user1)], []) assign('avocado.view_datafield', user1, self.is_manager) # Still nothing since user1 has no permission for salary self.assertEqual([x.pk for x in DataConcept.objects.published(user1)], []) assign('avocado.view_datafield', user1, self.salary) # Now user1 can see the concept self.assertEqual([x.pk for x in DataConcept.objects.published(user1)], [concept.pk]) user2 = User.objects.create_user('user2', 'user2') # `user2` is not assigned self.assertEqual([x.pk for x in DataConcept.objects.published(user2)], []) # Remove the fields from the concept and it should no longer appear # as published. DataConceptField.objects.filter(concept=concept).delete() self.assertEqual([x.pk for x in DataConcept.objects.published()], [])
def setUp(self): management.call_command('avocado', 'init', 'tests', quiet=True) first_name_field = DataField.objects.get_by_natural_key( 'tests', 'employee', 'first_name') first_name_field.description = 'First Name' first_name_field.save() last_name_field = DataField.objects.get_by_natural_key( 'tests', 'employee', 'last_name') last_name_field.description = 'Last Name' last_name_field.save() title_field = DataField.objects.get_by_natural_key( 'tests', 'title', 'name') title_field.description = 'Employee Title' title_field.save() salary_field = DataField.objects.get_by_natural_key( 'tests', 'title', 'salary') salary_field.description = 'Salary' salary_field.save() is_manager_field = DataField.objects.get_by_natural_key( 'tests', 'employee', 'is_manager') is_manager_field.description = 'Is a Manager?' is_manager_field.save() employee_concept = DataConcept() employee_concept.name = 'Employee' employee_concept.description = 'A Single Employee' employee_concept.save() DataConceptField(concept=employee_concept, field=first_name_field, order=1).save() DataConceptField(concept=employee_concept, field=last_name_field, order=2).save() DataConceptField(concept=employee_concept, field=is_manager_field, order=3).save() DataConceptField(concept=employee_concept, field=title_field, order=4).save() DataConceptField(concept=employee_concept, field=salary_field, order=5).save() self.concepts = [employee_concept] self.query = models.Employee.objects.values_list( 'first_name', 'last_name', 'is_manager', 'title__name', 'title__salary')
def test_dataview_order_by(self): f = DataField(app_name='lexicon', model_name='month', field_name='id') f.save() c = DataConcept() c.save() cf = DataConceptField(field=f, concept=c) cf.save() v = DataView({'ordering': [c.pk]}) qs = Month.objects.filter(label__startswith='J').values('id') self.assertEqual(str(v.apply(qs).query), 'SELECT "lexicon_month"."id" FROM "lexicon_month" WHERE "lexicon_month"."label" LIKE J% ESCAPE \'\\\' ORDER BY "lexicon_month"."order" ASC')
def setUp(self): super(ConceptFieldResourceTestCase, self).setUp() self.name_field = DataField.objects.get_by_natural_key( 'tests', 'title', 'name') self.salary_field = DataField.objects.get_by_natural_key( 'tests', 'title', 'salary') self.boss_field = DataField.objects.get_by_natural_key( 'tests', 'title', 'boss') c1 = DataConcept(name='Title', published=True) c1.save() DataConceptField(concept=c1, field=self.name_field, order=1).save() DataConceptField(concept=c1, field=self.salary_field, order=2).save() DataConceptField(concept=c1, field=self.boss_field, order=3).save()
def setUp(self): management.call_command('avocado', 'init', 'tests', publish=False, concepts=False, quiet=True) f1 = DataField.objects.get_by_natural_key('tests', 'employee', 'first_name') f2 = DataField.objects.get_by_natural_key('tests', 'employee', 'last_name') self.c = DataConcept() self.c.save() DataConceptField(concept=self.c, field=f1).save() DataConceptField(concept=self.c, field=f2).save()
def setUp(self): management.call_command('avocado', 'init', 'tests', quiet=True) f1 = DataField.objects.get(pk=1) f2 = DataField.objects.get(pk=2) c1 = DataConcept() c1.save() DataConceptField(concept=c1, field=f1).save() DataConceptField(concept=c1, field=f2).save() self.request = HttpRequest() self.request.session = SessionStore() self.request.session.save()
def setUp(self): management.call_command('avocado', 'init', 'tests', publish=False, concepts=False, quiet=True) f1 = DataField.objects.get(pk=1) f2 = DataField.objects.get(pk=2) c1 = DataConcept() c1.save() DataConceptField(concept=c1, field=f1).save() DataConceptField(concept=c1, field=f2).save()
def setUp(self): management.call_command('avocado', 'init', 'tests', quiet=True) f1 = DataField.objects.get_by_natural_key('tests', 'employee', 'first_name') f2 = DataField.objects.get_by_natural_key('tests', 'employee', 'last_name') self.c = DataConcept() self.c.save() DataConceptField(concept=self.c, field=f1).save() DataConceptField(concept=self.c, field=f2).save() self.request = HttpRequest() self.request.session = SessionStore() self.request.session.save()
def test_format(self): name_field = DataField.objects.get_by_natural_key( 'tests', 'title', 'name') salary_field = DataField.objects.get_by_natural_key( 'tests', 'title', 'salary') boss_field = DataField.objects.get_by_natural_key( 'tests', 'title', 'boss') concept = DataConcept(name='Title') concept.save() DataConceptField(concept=concept, field=name_field, order=1).save() DataConceptField(concept=concept, field=salary_field, order=2).save() DataConceptField(concept=concept, field=boss_field, order=3).save() values = ['CEO', 100000, True] self.assertEqual( concept.format(values), OrderedDict([(u'name', u'CEO'), (u'salary', 100000), (u'boss', True)])) self.assertEqual(concept._formatter_cache[0], None) from avocado.formatters import Formatter, registry as formatters class HtmlFormatter(Formatter): def to_html(self, values, **context): fvalues = self(values, preferred_formats=['string']) return OrderedDict({ 'profile': '<span>' + '</span><span>'.join(fvalues.values()) + '</span>' }) to_html.process_multiple = True formatters.register(HtmlFormatter, 'HTML') concept.formatter_name = 'HTML' self.assertEqual( concept.format(values, preferred_formats=['html']), OrderedDict([ ('profile', u'<span>CEO</span><span>100000</span><span>True</span>') ]))
def test_dataview_order_by(self): f = DataField(app_name='tests', model_name='month', field_name='id') f.save() c = DataConcept() c.save() cf = DataConceptField(field=f, concept=c) cf.save() v = DataView({'ordering': [[c.pk, 'asc']]}) qs = Month.objects.filter(label__startswith='J').values('id') self.assertEqual( unicode(v.apply(qs).query), 'SELECT "tests_month"."id" FROM "tests_month" WHERE "tests_month"."label" LIKE J% ESCAPE \'\\\' ORDER BY "tests_month"."order" ASC' )
def setUp(self): management.call_command('avocado', 'sync', 'openmrs') birthdate_field = DataField.objects.get_by_natural_key( 'openmrs', 'patient', 'birthdate') estimate_field = DataField.objects.get_by_natural_key( 'openmrs', 'patient', 'birthdate_estimated') self.concept = concept = DataConcept(name="Birthdate") concept.save() DataConceptField(concept=concept, field=birthdate_field, order=1).save() DataConceptField(concept=concept, field=estimate_field, order=2).save() formatter = registry.get('Age') self.f = formatter(concept)
def setUp(self): management.call_command('avocado', 'init', 'tests', quiet=True) name_field = DataField.objects.get_by_natural_key( 'tests', 'title', 'name') salary_field = DataField.objects.get_by_natural_key( 'tests', 'title', 'salary') boss_field = DataField.objects.get_by_natural_key( 'tests', 'title', 'boss') self.concept = concept = DataConcept(name='Title') concept.save() DataConceptField(concept=concept, field=name_field, order=1).save() DataConceptField(concept=concept, field=salary_field, order=2).save() DataConceptField(concept=concept, field=boss_field, order=3).save() self.values = ['CEO', 100000, True] self.f = Formatter(concept)
def test_unique_keys(self): title_name = DataField.objects.get_by_natural_key( 'tests', 'title', 'name') project_name = DataField.objects.get_by_natural_key( 'tests', 'project', 'name') concept = DataConcept() concept.save() DataConceptField(concept=concept, field=title_name, order=1).save() DataConceptField(concept=concept, field=project_name, order=2).save() f = Formatter(concept) self.assertEqual( OrderedDict([ ('title__name', 'one'), ('project__name', 'two'), ]), f(['one', 'two']))
def test_unique_keys(self): title_name = DataField.objects.get_by_natural_key( 'tests', 'title', 'name') project_name = DataField.objects.get_by_natural_key( 'tests', 'project', 'name') concept = DataConcept() concept.save() DataConceptField(concept=concept, field=title_name, order=1).save() DataConceptField(concept=concept, field=project_name, order=2).save() f = Formatter(concept=concept) meta = f.get_meta() names = [x['name'] for x in meta['header']] self.assertEqual(names, ['title__name', 'project__name'])
def create_dataconcept_single(self, request, queryset): fields = list(queryset) # If only a single field is selected with this action, directly map if len(fields) == 1: DataConcept.objects.create_from_field(fields[0]) return max_length = DataConcept._meta.get_field_by_name('name')[0].max_length name = ', '.join([f.name for f in fields])[:max_length - 5] + '...' concept = DataConcept(name=u'"{0}"'.format(name)) concept.save() for i, datafield in enumerate(queryset): DataConceptField(concept=concept, field=datafield, order=i).save()
def test_field_for_concept(self): f = DataField.objects.get(id=4) c1 = DataConcept() c2 = DataConcept() c1.save() c2.save() cf = DataConceptField(concept=c1, field=f) cf.save() self.assertEqual(parsers.datacontext.validate({ 'concept': c1.pk, 'field': 4, 'operator': 'exact', 'value': 'CEO' }, tree=Employee), None) # Invalid concept self.assertRaises(ValidationError, parsers.datacontext.validate, { 'concept': c2.pk, 'field': 4, 'operator': 'exact', 'value': 'CEO' }, tree=Employee)
def create_from_field(self, field, save=True, **kwargs): """Derives a DataConcept from this DataField's descriptors. Additional keyword arguments can be passed in to customize the new DataConcept object. The DataConcept can also be optionally saved by setting the `save` flag. """ for key, value, in field.descriptors.iteritems(): kwargs.setdefault(key, value) concept = self.model(**kwargs) if save: from avocado.models import DataConceptField concept.save() cfield = DataConceptField(field=field, concept=concept) concept.concept_fields.add(cfield) return concept
def test_get_all_category_sort(self): # Create some temporary concepts and categories. cat1 = DataCategory(name='Category1', order=2.0, published=True) cat1.save() c1 = DataConcept(name='B', published=True, category=cat1, order=1) c1.save() field1 = DataConceptField(concept=c1, field=self.name_field, order=1) field1.save() c2 = DataConcept(name='C', published=True, category=cat1, order=2) c2.save() field2 = DataConceptField(concept=c2, field=self.name_field, order=1) field2.save() c3 = DataConcept(name='A', published=True, category=cat1, order=3) c3.save() field3 = DataConceptField(concept=c3, field=self.name_field, order=1) field3.save() # Check that category ordering is happening by default. response = self.client.get('/api/concepts/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertEqual(len(json.loads(response.content)), 5) names = [concept.get('name', '') for concept in json.loads(response.content)] self.assertEqual(names, ['Title', 'Name', 'B', 'C', 'A']) # Reverse the ordering of the categories. response = self.client.get('/api/concepts/', {'order': 'desc'}, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertEqual(len(json.loads(response.content)), 5) names = [concept.get('name', '') for concept in json.loads(response.content)] self.assertEqual(names, ['B', 'C', 'A', 'Title', 'Name']) # Order by concept name in addition to category. response = self.client.get('/api/concepts/', {'sort': 'name'}, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertEqual(len(json.loads(response.content)), 5) names = [concept.get('name', '') for concept in json.loads(response.content)] self.assertEqual(names, ['Name', 'Title', 'A', 'B', 'C']) # Reverse the name and category sorting. response = self.client.get('/api/concepts/', {'sort': 'name', 'order': 'desc'}, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertEqual(len(json.loads(response.content)), 5) names = [concept.get('name', '') for concept in json.loads(response.content)] self.assertEqual(names, ['C', 'B', 'A', 'Title', 'Name']) c1.delete() c2.delete() c3.delete() field1.delete() field2.delete() field3.delete() cat1.delete()
def _migrate_concept(self, model, migrate_func, **options): no_input = options.get('no_input') total_migrated = 0 for lc in model.objects.iterator(): field_nks = list( lc.fields.values('app_name', 'model_name', 'field_name').distinct()) field_cond = Q() for f in field_nks: field_cond = field_cond | Q(**f) fields = DataField.objects.filter(field_cond).distinct() # Mismatch of fields from new to old if len(fields) != len(field_nks): print( 'One or more fields mismatched for "{0}". ' 'Skipping...'.format(lc)) continue matches = DataConcept.objects.filter(name=lc.name) # Filter concepts by existence of fields for f in fields: matches = matches.filter(fields__app_name=f.app_name, fields__model_name=f.model_name, fields__field_name=f.field_name) num = len(matches) if num > 1: print('{0} have the same name and fields. ' 'Skipping...'.format(num)) continue if num == 1: c = matches[0] existing = True if not no_input: override = True while True: response = raw_input(u'Match found for "{0}". ' 'Override? [n/Y] '.format(c)) if not response: break if response.lower() == 'n': override = False break if not override: continue else: c = DataConcept(queryable=False, viewable=False) existing = False c.name = lc.name c.order = lc.order c.published = lc.is_public # This looks odd, but this handles choosing the longer of the two # descriptions for criterion and column if both exist. if not c.description or lc.description and \ len(lc.description) > len(c.description): c.description = lc.description if lc.category: try: kwargs = { 'name__iexact': lc.category.name, } # Filter by parent if one exists since categories with the # same name can exists as sub-categories. if lc.category.parent_id: kwargs['parent__name'] = lc.category.parent.name c.category = DataCategory.objects.get(**kwargs) except DataCategory.DoesNotExist: pass # Apply migration specific function to concept from legacy concept migrate_func(c, lc) # Save for foreign key references to concept fields c.save() cfs = [] if not existing: lcfs = list(lc.conceptfields.select_related('field')) # Dict of legacy concept fields to the new field it # corresponds to lcf_map = {} for lcf in lcfs: for f in fields: # Match and break if lcf.field.natural_key() == f.natural_key(): lcf_map[lcf.pk] = f break # Map fields to # Iterate over all legacy concept fields and create the new # concept fields for lcf in lcfs: f = lcf_map[lcf.pk] cfs.append( DataConceptField(concept=c, field=f, name=lcf.name, order=lcf.order)) # Save concept fields for cf in cfs: cf.save() print 'Migrated "{0}"'.format(c) total_migrated += 1 print '{0} migrated: {1}'.format(model.__name__, total_migrated)
def setUp(self): super(FieldValidatorTestCase, self).setUp() self.field = DataField.objects.get_by_natural_key('tests.title.salary') self.concept = DataConcept(name='Salary') self.concept.save() DataConceptField(concept=self.concept, field=self.field).save()
def test_get_all_category_sort(self): # Create some temporary concepts and categories cat1 = DataCategory(name='Category1', order=1.0, published=True) cat1.save() c1 = DataConcept(name='B', published=True, category=cat1) c1.save() field1 = DataConceptField(concept=c1, field=self.name_field, order=1) field1.save() c2 = DataConcept(name='C', published=True, category=cat1) c2.save() field2 = DataConceptField(concept=c2, field=self.name_field, order=1) field2.save() c3 = DataConcept(name='A', published=True, category=cat1) c3.save() field3 = DataConceptField(concept=c3, field=self.name_field, order=1) field3.save() # Check that category ordering is happening by default response = self.client.get('/api/concepts/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 200) self.assertEqual(len(json.loads(response.content)), 5) names = [concept.get('name', '') for concept in json.loads(response.content)] self.assertEqual(names, ['Title', 'Name', 'B', 'C', 'A']) # Reverse the ordering of the categories response = self.client.get('/api/concepts/', {'order': 'desc'}, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 200) self.assertEqual(len(json.loads(response.content)), 5) names = [concept.get('name', '') for concept in json.loads(response.content)] self.assertEqual(names, ['B', 'C', 'A', 'Title', 'Name']) # Order by concept name in addition to category response = self.client.get('/api/concepts/', {'sort': 'name'}, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 200) self.assertEqual(len(json.loads(response.content)), 5) names = [concept.get('name', '') for concept in json.loads(response.content)] self.assertEqual(names, ['Name', 'Title', 'A', 'B', 'C']) # Reverse the name and category sorting response = self.client.get('/api/concepts/', {'sort': 'name', 'order': 'desc'}, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 200) self.assertEqual(len(json.loads(response.content)), 5) names = [concept.get('name', '') for concept in json.loads(response.content)] self.assertEqual(names, ['C', 'B', 'A', 'Title', 'Name']) c1.delete() c2.delete() c3.delete() field1.delete() field2.delete() field3.delete() cat1.delete()