def post(self, request, **kwargs): instance = self.get_object(request, **kwargs) if self._requestor_can_fork(request, instance): fork = DataQuery(name=instance.name, description=instance.description, view_json=instance.view_json, context_json=instance.context_json, parent=instance) if getattr(request, 'user', None): fork.user = request.user elif request.session.session_key: fork.session_key = request.session.session_key fork.save() request.session.modified = True posthook = functools.partial(query_posthook, request=request) data = serialize(fork, posthook=posthook, **templates.Query) return self.render(request, data, status=codes.created) data = { 'message': 'Cannot fork query', } return self.render(request, data, status=codes.unauthorized)
def test_put(self): # Add a query so we can try to update it later query = DataQuery(user=self.user, name='Query 1') query.save() response = self.client.get('/api/queries/1/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertTrue(response.content) # Attempt to update the name via a PUT request response = self.client.put('/api/queries/1/', data=u'{"name":"New Name"}', content_type='application/json') self.assertEqual(response.status_code, codes.ok) # Make sure our changes from the PUT request are persisted response = self.client.get('/api/queries/1/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertTrue(response.content) self.assertEqual(json.loads(response.content)['name'], 'New Name') # Make a PUT request with invalid JSON and make sure we get an # unprocessable status code back. response = self.client.put('/api/queries/1/', data=u'{"view_json":"[~][~]"}', content_type='application/json') self.assertEqual(response.status_code, codes.unprocessable_entity)
def test_count(self): c = DataConcept.objects.get(fields__model_name='title', fields__field_name='salary') json = { 'context': { 'field': 'tests.title.salary', 'operator': 'gt', 'value': '1000' }, 'view': [{ 'concept': c.id, 'visible': True, }] } query = DataQuery(json) # Default tree is Employee so we should get 6 unique employee objects # regardless of distinct setting since all are distinct. self.assertEqual(query.count(), 6) self.assertEqual(query.count(distinct=False), 6) # Switching the tree should allow us to exercise the distinct keyword # since there are 3 titles all with the same 15,000 unit salary. We # need to eliminate the PK so that we are only getting salaries # back. Including the PK causes everything to be unique. self.assertEqual(query.count(tree='title', include_pk=False), 5) self.assertEqual( query.count(tree='title', include_pk=False, distinct=False), 7)
def test_no_create_on_share(self): # Make sure we are starting with the anticipated number of users. self.assertEqual(User.objects.count(), 1) # Assign an email to the existing user User.objects.all().update(email=self.existing_email) query = DataQuery(template=True, default=True) query.save() self.assertEqual(query.shared_users.count(), 0) # Test when both settings are False response = query.share_with_user(self.existing_email) self.assertEqual(response, False) with self.settings(AVOCADO_SHARE_BY_EMAIL=True): # Share with all the emails but, with create_user set to False, the # query should only be shared with the 1 existing user. [query.share_with_user(e, create_user=False) for e in self.emails] # Check that the user count increased for the email-based users self.assertEqual(User.objects.count(), 1) # Check that the users are in the query's shared_users self.assertEqual(query.shared_users.count(), 1)
def test_get(self): query = DataQuery(user=self.user) query.save() response = self.client.get('/api/queries/revisions/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertEqual(len(json.loads(response.content)), 1)
def test_session(self): query = DataQuery(session=True, user=self.user) query.save() response = self.client.get('/api/queries/session/stats/', HTTP_ACCEPT='application/json') data = json.loads(response.content) self.assertEqual(data['distinct_count'], 6) self.assertEqual(data['record_count'], 6)
def test_get(self): query = DataQuery(user=self.user) query.save() child_query = DataQuery(name='Child 1', parent=query) child_query.save() child_query = DataQuery(name='Child 2', parent=query) child_query.save() url = '/api/queries/{0}/'.format(query.pk) response = self.client.get(url, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertTrue(response.content) self.assertLess(query.accessed, DataQuery.objects.get(pk=query.pk).accessed) # When we access a query it should contain a valid link to the forks # of that query. data = json.loads(response.content) response = self.client.get(data['_links']['forks']['href'], HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertTrue(response.content) self.assertEqual(len(json.loads(response.content)), 2) # Make sure we get a codes.not_found when accessing a query that # doesn't exist response = self.client.get('/api/queries/123456/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.not_found)
def test_shared_users_count(self): u1 = User(username='******', email='*****@*****.**') u1.save() u2 = User(username='******', email='*****@*****.**') u2.save() query = DataQuery(user=self.user) query.save() query.shared_users.add(u1) query.shared_users.add(u2) query.save() response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 1) content = json.loads(response.content)[0] self.assertEqual(len(content['shared_users']), 2) u3 = User(username='******', email='*****@*****.**') u3.save() u4 = User(username='******', email='*****@*****.**') u4.save() query.shared_users.remove(u1) query.shared_users.add(u3) query.shared_users.add(u4) query.save() response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 1) content = json.loads(response.content)[0] self.assertEqual(len(content['shared_users']), 3)
def test_add_shared_user(self): # Make sure we are starting with the anticipated number of users. self.assertEqual(User.objects.count(), 1) # Assign an email to the existing user User.objects.update(email=self.existing_email, username=self.existing_username) query = DataQuery(template=True, default=True) query.save() self.assertEqual(query.shared_users.count(), 0) # Try add an existing user to shared users by username query.share_with_user(self.existing_username) self.assertEqual(query.shared_users.count(), 1) [query.share_with_user(e) for e in self.emails] # Looking up non existant users with usernames should not # create new users [query.share_with_user(u) for u in self.usernames] # Check that the user count increased for the email-based users # and no extra users were created when queried w/ username self.assertEqual(User.objects.count(), 4) # Check that the users are in the query's shared_users self.assertEqual(query.shared_users.count(), 4)
def test_delete(self): query = DataQuery(user=self.user, name="TestQuery") query.save() session_query = DataQuery(user=self.user, name="SessionQuery", session=True) session_query.save() user1 = User(username='******', first_name='Shared', last_name='User', email='*****@*****.**') user1.save() query.shared_users.add(user1) user2 = User(username='******', first_name='Shared', last_name='User', email='') user2.save() query.shared_users.add(user2) user3 = User(username='******', first_name='Shared', last_name='User', email='*****@*****.**') user3.save() query.shared_users.add(user3) response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 2) response = self.client.delete('/api/queries/1/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.no_content) # Since the delete handler send email asynchronously, wait for a while # while the mail goes through. time.sleep(5) # Make sure the mail was sent self.assertEqual(len(mail.outbox), 1) # Make sure the subject is correct self.assertEqual(mail.outbox[0].subject, "'TestQuery' has been deleted") # Make sure the recipient list is correct self.assertSequenceEqual( mail.outbox[0].to, ['*****@*****.**', '', '*****@*****.**']) response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 1) # Make sure that we cannot delete the session query response = self.client.delete('/api/queries/2/') self.assertEqual(response.status_code, codes.bad_request) response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 1)
def test_duplicate_share(self): query = DataQuery(template=True, default=True) query.save() [query.share_with_user(e) for e in self.emails] share_count = query.shared_users.count() user_count = User.objects.count() # Make sure that requests to share with users that are already shared # with don't cause new user or shared_user entries. [query.share_with_user(e) for e in self.emails] self.assertEqual(share_count, query.shared_users.count()) self.assertEqual(user_count, User.objects.count())
def test_processor(self): query = DataQuery(session=True, user=self.user) query.save() response = self.client.get('/api/queries/{0}/stats/'.format(query.pk), HTTP_ACCEPT='application/json') data = json.loads(response.content) self.assertEqual(data['distinct_count'], 6) self.assertEqual(data['record_count'], 6) response = self.client.get('/api/queries/{0}/stats/?processor=manager' .format(query.pk), HTTP_ACCEPT='application/json') data = json.loads(response.content) self.assertEqual(data['distinct_count'], 1) self.assertEqual(data['record_count'], 1)
def test_processor(self): query = DataQuery(session=True, user=self.user) query.save() response = self.client.get('/api/queries/{0}/stats/'.format(query.pk), HTTP_ACCEPT='application/json') data = json.loads(response.content) self.assertEqual(data['distinct_count'], 6) self.assertEqual(data['record_count'], 6) response = self.client.get( '/api/queries/{0}/stats/?processor=manager'.format(query.pk), HTTP_ACCEPT='application/json') data = json.loads(response.content) self.assertEqual(data['distinct_count'], 1) self.assertEqual(data['record_count'], 1)
def get_object(self, request, pk=None, session=None, **kwargs): if not pk and not session: raise ValueError('A pk or session must used for the lookup') if not hasattr(request, 'instance'): queryset = self.get_queryset(request, **kwargs) instance = None try: if pk: instance = queryset.get(pk=pk) else: instance = queryset.get(session=True) except self.model.DoesNotExist: if session: filters = self.get_request_filters(request) try: context = DataContext.objects.filter(**filters)\ .get(session=True) view = DataView.objects.filter(**filters)\ .get(session=True) instance = DataQuery(context_json=context.json, view_json=view.json) except (DataContext.DoesNotExist, DataView.DoesNotExist): pass request.instance = instance return request.instance
def test_clean(self): # Save default template query = DataQuery(template=True, default=True) query.save() # Save new template (not default) query2 = DataQuery(template=True) query2.save() # Try changing the second query to the default query2.default = True self.assertRaises(ValidationError, query2.save) query.save()
def test_get_session(self): query = DataQuery(user=self.user, name='Query', session=True) query.save() # All results for session query. response = self.client.get('/api/queries/session/results/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertTrue(response.content) # Single page of results for session query. response = self.client.get('/api/queries/session/results/3/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertTrue(response.content) # Page range of results for session query. response = self.client.get('/api/queries/session/results/1...5/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertTrue(response.content) query.session = False query.save() response = self.client.get('/api/queries/session/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.not_found)
def test_apply(self): attrs = { 'context': { 'field': 'tests.title.boss', 'operator': 'exact', 'value': True }, 'view': { 'columns': [1], } } query = DataQuery(attrs) self.assertEqual(unicode(query.apply(tree=Employee).query), 'SELECT DISTINCT "tests_employee"."id", "tests_office"."location", "tests_title"."name" FROM "tests_employee" INNER JOIN "tests_title" ON ("tests_employee"."title_id" = "tests_title"."id") INNER JOIN "tests_office" ON ("tests_employee"."office_id" = "tests_office"."id") WHERE "tests_title"."boss" = True ') query = DataQuery({'view': {'ordering': [(1, 'desc')]}}) queryset = Employee.objects.all().distinct() self.assertEqual(unicode(query.apply(queryset=queryset).query), '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')
def test_only_shared(self): query = DataQuery() query.save() query.shared_users.add(self.user) query.save() query2 = DataQuery() query2.save() # Ensure that there are 2 queries to start self.assertEqual(DataQuery.objects.count(), 2) response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 1) query = json.loads(response.content)[0] self.assertFalse(query['is_owner']) self.assertFalse('shared_users' in query)
def test_add_shared_user(self): # Make sure we are starting with the anticipated number of users. self.assertEqual(User.objects.count(), 1) # Assign an email to the existing user User.objects.all().update(email=self.existing_email) query = DataQuery(template=True, default=True) query.save() self.assertEqual(query.shared_users.count(), 0) [query.share_with_user(e) for e in self.emails] # Check that the user count increased for the email-based users self.assertEqual(User.objects.count(), 4) # Check that the users are in the query's shared_users self.assertEqual(query.shared_users.count(), 4)
def test_get_session(self): # Make sure we have a session query. query = DataQuery(user=self.user, name='Query', session=True) query.save() # All results for session query. response = self.client.get('/api/async/queries/session/results/', HTTP_ACCEPT='application/json') self.assertEqual( response.status_code, HttpResponseRedirect.status_code) normal_job_id = response['Location'].split('/')[-2] # Single page of results for session query. response = self.client.get('/api/async/queries/session/results/3/', HTTP_ACCEPT='application/json') self.assertEqual( response.status_code, HttpResponseRedirect.status_code) paged_job_id = response['Location'].split('/')[-2] # Page range of results for session query. response = self.client.get('/api/async/queries/session/results/1...5/', HTTP_ACCEPT='application/json') self.assertEqual( response.status_code, HttpResponseRedirect.status_code) range_job_id = response['Location'].split('/')[-2] # The three requests above should have triggered 3 queued jobs. self.assertEqual(utils.get_job_count(), 3) for job_id in [normal_job_id, paged_job_id, range_job_id]: self.assert_job_status_equal( utils.get_job(job_id), 'queued') # Sleeping a couple seconds should leave plenty of time for the worker # to do its thing and finish up the three jobs from above. utils.run_jobs() time.sleep(3) # The three previous requests should now all be completed and their # items should match what we expect. for job_id in [normal_job_id, paged_job_id, range_job_id]: self.assert_job_status_equal( utils.get_job(job_id), 'finished') self.assert_job_result_equal(utils.get_job(job_id), [])
def test_parse(self): attrs = { 'context': { 'type': 'and', 'children': [{ 'field': 'tests.title.name', 'operator': 'exact', 'value': 'CEO', }] }, 'view': { 'ordering': [(1, 'desc')] } } query = DataQuery(attrs) node = query.parse(tree=Employee) self.assertEqual(str(node.datacontext_node.condition), "(AND: ('title__name__exact', u'CEO'))") self.assertEqual(str(node.dataview_node.ordering), "[(1, 'desc')]")
def test_session_owner(self): # No user for this one.. self.client.logout() # Access endpoint to initialize the anonymous session. This feels # like a hack, but there seems to be no other way to initialize the # session with a key self.client.get('/api/') # Fake the session key query = DataQuery(session_key=self.client.session.session_key) query.save() response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertEqual(len(json.loads(response.content)), 1) query = json.loads(response.content)[0] self.assertTrue(query['is_owner'])
def test_session_owner(self): # No user for this one.. self.client.logout() # Access endpoint to initialize the anonymous session. This feels # like a hack, but there seems to be no other way to initialize the # session with a key self.client.get('/api/') # Fake the session key query = DataQuery(session_key=self.client.session.session_key) query.save() response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, 200) self.assertEqual(len(json.loads(response.content)), 1) query = json.loads(response.content)[0] self.assertTrue(query['is_owner'])
def test_get(self): query = DataQuery(name='Q1', public=True) query.save() query = DataQuery(name='Q2', public=True) query.save() query = DataQuery(name='Q3') query.save() self.assertEqual(DataQuery.objects.distinct().count(), 3) response = self.client.get('/api/queries/public/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertTrue(response.content) self.assertEqual(len(json.loads(response.content)), 2)
def test_no_create_on_share(self): # Make sure we are starting with the anticipated number of users. self.assertEqual(User.objects.count(), 1) # Assign an email to the existing user User.objects.all().update(email=self.existing_email) query = DataQuery(template=True, default=True) query.save() self.assertEqual(query.shared_users.count(), 0) # Share with all the emails but, with create_user set to False, the # query should only be shared with the 1 existing user. [query.share_with_user(e, create_user=False) for e in self.emails] # Check that the user count increased for the email-based users self.assertEqual(User.objects.count(), 1) # Check that the users are in the query's shared_users self.assertEqual(query.shared_users.count(), 1)
def test_get(self): query = DataQuery(user=self.user) query.save() child_query = DataQuery(name='Child 1', parent=query) child_query.save() child_query = DataQuery(name='Child 2', parent=query) child_query.save() url = '/api/queries/{0}/'.format(query.pk) response = self.client.get(url, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertTrue(response.content) self.assertLess(query.accessed, DataQuery.objects.get(pk=query.pk).accessed) # When we access a query it should contain a valid link to the forks # of that query. self.assertTrue('forks' in response['Link-Template']) links = response['Link-Template'].split(',') for link in links: if 'forks' in link: # NOTE: This link template formatting would normally be done # on the client side but we do it manually once here to extract # and format the link to the forks. fields = link.split(';') href = fields[0].replace('<', '')\ .replace('>', '')\ .replace('{id}', str(query.pk))\ .strip() response = self.client.get( href, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertTrue(response.content) self.assertEqual(len(json.loads(response.content)), 2) # Make sure we get a codes.not_found when accessing a query that # doesn't exist response = self.client.get('/api/queries/123456/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.not_found)
def test_parse(self): c = DataConcept.objects.get(fields__model_name='title', fields__field_name='name') attrs = { 'context': { 'type': 'and', 'children': [{ 'field': 'tests.title.name', 'operator': 'exact', 'value': 'CEO', }] }, 'view': [{ 'concept': c.pk, 'sort': 'desc', }], } query = DataQuery(attrs) node = query.parse(tree=Employee) self.assertEqual(str(node.datacontext_node.condition), "(AND: ('title__name__exact', u'CEO'))")
def test_apply(self): c = DataConcept.objects.get(fields__model_name='office', fields__field_name='location') attrs = { 'context': { 'field': 'tests.title.boss', 'operator': 'exact', 'value': True }, 'view': [{ 'concept': c.pk, 'visible': True, }], } query = DataQuery(attrs) self.assertEqual( unicode(query.apply(tree=Employee).query).replace(' ', ''), 'SELECT DISTINCT "tests_employee"."id", ' '"tests_office"."location" FROM ' '"tests_employee" INNER JOIN "tests_title" ON ' '("tests_employee"."title_id" = "tests_title"."id") INNER JOIN ' '"tests_office" ON ("tests_employee"."office_id" = ' '"tests_office"."id") WHERE "tests_title"."boss" = True ' .replace(' ', '')) query = DataQuery({'view': {'ordering': [(c.pk, 'desc')]}}) queryset = Employee.objects.all().distinct() self.assertEqual( unicode(query.apply(queryset=queryset).query).replace(' ', ''), 'SELECT DISTINCT "tests_employee"."id", ' '"tests_office"."location" FROM ' '"tests_employee" INNER JOIN "tests_office" ON ' '("tests_employee"."office_id" = "tests_office"."id") ' 'ORDER BY "tests_office"."location" DESC'.replace(' ', ''))
def test_delete(self): query_name = u'ĘƞĵôƔ ťƕîš ǫųęŕƳ' query = DataQuery(user=self.user, name=query_name) query.save() session_query = DataQuery(user=self.user, name="SessionQuery", session=True) session_query.save() user1 = User(username='******', first_name='Shared', last_name='User', email='*****@*****.**') user1.save() query.shared_users.add(user1) user2 = User(username='******', first_name='Shared', last_name='User', email='') user2.save() query.shared_users.add(user2) user3 = User(username='******', first_name='Shared', last_name='User', email='*****@*****.**') user3.save() query.shared_users.add(user3) response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 2) response = self.client.delete('/api/queries/{0}/'.format(query.pk), HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.no_content) # Since the delete handler send email asynchronously, wait for a while # while the mail goes through. time.sleep(5) # Make sure the mail was sent self.assertEqual(len(mail.outbox), 1) # Make sure the subject is correct self.assertEqual(mail.outbox[0].subject, u"'{0}' has been deleted".format(query_name)) # Make sure the recipient list is correct self.assertSequenceEqual( mail.outbox[0].to, ['*****@*****.**', '', '*****@*****.**']) response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 1) # Make sure that we cannot delete the session query response = self.client.delete('/api/queries/{0}/' .format(session_query.pk)) self.assertEqual(response.status_code, codes.bad_request) response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 1)
def test_get_session(self): query = DataQuery(user=self.user, name='Query', session=True) query.save() response = self.client.get('/api/queries/session/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) self.assertTrue(response.content) query.session = False query.save() response = self.client.get('/api/queries/session/', HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.not_found)
def test_validate(self): attrs = { 'context': { 'field': 'tests.title.name', 'operator': 'exact', 'value': 'CEO', 'language': 'Name is CEO' }, 'view': { 'columns': [1], } } exp_attrs = deepcopy(attrs) exp_attrs['view'] = [{'concept': 1}] self.assertEqual(DataQuery.validate(deepcopy(attrs), tree=Employee), exp_attrs)
def test_shared_users_count(self): u1 = User(username='******', email='*****@*****.**') u1.save() u2 = User(username='******', email='*****@*****.**') u2.save() query = DataQuery(user=self.user) query.save() query.shared_users.add(u1) query.shared_users.add(u2) query.save() response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 1) self.assertEqual( response['Link-Template'], ('<http://testserver/api/queries/{id}/>; rel="self", ' '<http://testserver/api/queries/{id}/stats/>; rel="stats", ' '<http://testserver/api/queries/{id}/forks/>; rel="forks", ' '<http://testserver/api/queries/{id}/results/>; rel="results"')) content = json.loads(response.content)[0] self.assertEqual(len(content['shared_users']), 2) u3 = User(username='******', email='*****@*****.**') u3.save() u4 = User(username='******', email='*****@*****.**') u4.save() query.shared_users.remove(u1) query.shared_users.add(u3) query.shared_users.add(u4) query.save() response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 1) content = json.loads(response.content)[0] self.assertEqual(len(content['shared_users']), 3)
def test_init(self): json = { 'context': { 'field': 'tests.title.salary', 'operator': 'gt', 'value': '1000' }, 'view': [], } query = DataQuery(json) self.assertEqual(query.context_json, json['context']) self.assertEqual(query.view_json, json['view']) # Test the json of the DataQuery properties too self.assertEqual(query.context.json, json['context']) self.assertEqual(query.view.json, json['view']) self.assertEqual(query.json, json)
def test_validate(self): c = DataConcept.objects.get(fields__model_name='title', fields__field_name='name') attrs = { 'context': { 'field': 'tests.title.name', 'operator': 'exact', 'value': 'CEO', 'cleaned_value': {'value': 'CEO', 'label': 'CEO'}, 'language': 'Name is CEO' }, 'view': [{ 'concept': c.pk, 'visible': True, }], } exp_attrs = deepcopy(attrs) self.assertEqual(DataQuery.validate(attrs, tree=Employee), exp_attrs)
def test_shared_users_count(self): u1 = User(username='******', email='*****@*****.**') u1.save() u2 = User(username='******', email='*****@*****.**') u2.save() query = DataQuery(user=self.user) query.save() query.shared_users.add(u1) query.shared_users.add(u2) query.save() response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 1) self.assertEqual(response['Link-Template'], ( '<http://testserver/api/queries/{id}/>; rel="self", ' '<http://testserver/api/queries/{id}/stats/>; rel="stats", ' '<http://testserver/api/queries/{id}/forks/>; rel="forks", ' '<http://testserver/api/queries/{id}/results/>; rel="results"' )) content = json.loads(response.content)[0] self.assertEqual(len(content['shared_users']), 2) u3 = User(username='******', email='*****@*****.**') u3.save() u4 = User(username='******', email='*****@*****.**') u4.save() query.shared_users.remove(u1) query.shared_users.add(u3) query.shared_users.add(u4) query.save() response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 1) content = json.loads(response.content)[0] self.assertEqual(len(content['shared_users']), 3)
def test_validate(self): c = DataConcept.objects.get(fields__model_name='title', fields__field_name='name') attrs = { 'context': { 'field': 'tests.title.name', 'operator': 'exact', 'value': 'CEO', 'cleaned_value': { 'value': 'CEO', 'label': 'CEO' }, 'language': 'Name is CEO' }, 'view': [{ 'concept': c.pk, 'visible': True, }], } exp_attrs = deepcopy(attrs) self.assertEqual(DataQuery.validate(attrs, tree=Employee), exp_attrs)
def test_apply(self): c = DataConcept.objects.get(fields__model_name='office', fields__field_name='location') attrs = { 'context': { 'field': 'tests.title.boss', 'operator': 'exact', 'value': True }, 'view': [{ 'concept': c.pk, 'visible': True, }], } query = DataQuery(attrs) self.assertEqual( unicode(query.apply(tree=Employee).query).replace(' ', ''), 'SELECT DISTINCT "tests_employee"."id", ' '"tests_office"."location" FROM ' '"tests_employee" INNER JOIN "tests_title" ON ' '("tests_employee"."title_id" = "tests_title"."id") INNER JOIN ' '"tests_office" ON ("tests_employee"."office_id" = ' '"tests_office"."id") WHERE "tests_title"."boss" = True '.replace( ' ', '')) query = DataQuery({'view': {'ordering': [(c.pk, 'desc')]}}) queryset = Employee.objects.all().distinct() self.assertEqual( unicode(query.apply(queryset=queryset).query).replace(' ', ''), 'SELECT DISTINCT "tests_employee"."id", ' '"tests_office"."location" FROM ' '"tests_employee" INNER JOIN "tests_office" ON ' '("tests_employee"."office_id" = "tests_office"."id") ' 'ORDER BY "tests_office"."location" DESC'.replace(' ', ''))
def test_apply(self): attrs = { 'context': { 'field': 'tests.title.boss', 'operator': 'exact', 'value': True }, 'view': { 'columns': [1], } } query = DataQuery(attrs) self.assertEqual( unicode(query.apply(tree=Employee).query), 'SELECT DISTINCT "tests_employee"."id", "tests_office"."location", "tests_title"."name" FROM "tests_employee" INNER JOIN "tests_title" ON ("tests_employee"."title_id" = "tests_title"."id") INNER JOIN "tests_office" ON ("tests_employee"."office_id" = "tests_office"."id") WHERE "tests_title"."boss" = True ' ) query = DataQuery({'view': {'ordering': [(1, 'desc')]}}) queryset = Employee.objects.all().distinct() self.assertEqual( unicode(query.apply(queryset=queryset).query), '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' )
def test_owner_and_shared(self): # Create a query this user owns query = DataQuery(user=self.user) query.save() # Create a query owned by and shared with no one query2 = DataQuery() query2.save() # Create a query with no owner but shared with this user query3 = DataQuery() query3.save() query3.shared_users.add(self.user) query3.save() self.assertEqual(DataQuery.objects.count(), 3) # Retrieve the queries shared with and owned by this user, the count # should be 2 since this user owns one and is the sharee on another. response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 2) # Verify that the order is descending based on accessed time. The 3rd # query was created most recently so it should be first in the list # over the 1st query. shared_queries = json.loads(response.content) self.assertEqual(shared_queries[0]['id'], query3.pk) self.assertEqual(shared_queries[1]['id'], query.pk) # Access the 1st query. This should make its accessed time update thus # making the 1st query the most recent of this users' shared queries. response = self.client.get('/api/queries/{0}/'.format(query.pk), HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, codes.ok) # Retrieve the queries shared with and owned by this user once again # to make sure the order has changed. response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 2) # Since the 1st query was just accessed, it should now be the first # query in the result followed by the 3rd query. shared_queries = json.loads(response.content) self.assertEqual(shared_queries[0]['id'], query.pk) self.assertEqual(shared_queries[1]['id'], query3.pk) # If we logout and submit the request without a user, there should # be 0 shared queries returned. self.client.logout() response = self.client.get('/api/queries/', HTTP_ACCEPT='application/json') self.assertEqual(len(json.loads(response.content)), 0)
def get_request_query(request, attrs=None): """ Resolves the appropriate DataQuery object for use from the request. """ # Attempt to derive the `attrs` from the request if attrs is None: if request.method == 'POST': attrs = request.data.get('query') elif request.method == 'GET': attrs = request.GET.get('query') # If the `attrs` could not be derived from the request(meaning no query # was explicity defined), try to construct the query by deriving a context # and view from the request. if attrs is None: json = {} context = get_request_context(request) if context: json['context'] = context.json view = get_request_view(request) if view: json['view'] = view.json return DataQuery(json) # If `attrs` were derived or supplied then validate them and return a # DataQuery based off the `attrs`. if isinstance(attrs, dict): # We cannot simply validate and create a DataQuery based off the # `attrs` as they are now because the context and or view might not # contain json but might instead be a pk or some other value. Use the # internal helper methods to construct the context and view objects # and build the query from the json of those objects' json. json = {} context = get_request_context(request, attrs=attrs) if context: json['context'] = context.json view = get_request_view(request, attrs=attrs) if view: json['view'] = view.json DataQuery.validate(json) return DataQuery(json) kwargs = {} # If an authenticated user made the request, filter by the user or # fallback to an active session key. if getattr(request, 'user', None) and request.user.is_authenticated(): kwargs['user'] = request.user else: # If not session has been created, this is a cookie-less user agent # which is most likely a bot or a non-browser client (e.g. cURL). if request.session.session_key is None: return DataQuery() kwargs['session_key'] = request.session.session_key # Assume it is a primary key and fallback to the sesssion try: kwargs['pk'] = int(attrs) except (ValueError, TypeError): kwargs['session'] = True try: return DataQuery.objects.get(**kwargs) except DataQuery.DoesNotExist: pass # Fallback to an instance based off the default template if one exists instance = DataQuery() default = DataQuery.objects.get_default_template() if default: instance.json = default.json return instance