Provides some basic tools for getting additional information about a lookup field.
Adds an optional 'value' parameter to the lookup endpoint so you can find a specific entry in the lookup table. Makes sure the data attribute returned on a lookup model is a dictionary, and not a string. Fixes a previous bug that would crop up if double spaces were used when performing a search.
This commit is contained in:
parent
d3ce1af1ce
commit
f183e12fe5
12
crc/api.yml
12
crc/api.yml
|
@ -703,18 +703,18 @@ paths:
|
||||||
description: The string to search for in the Value column of the lookup table.
|
description: The string to search for in the Value column of the lookup table.
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
- name: value
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
description: An alternative to query, this accepts the specific value or id selected in a dropdown list or auto-complete, and will return the one matching record. Useful for getting additional details about an item selected in a dropdown.
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
- name: limit
|
- name: limit
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
description: The total number of records to return, defaults to 10.
|
description: The total number of records to return, defaults to 10.
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
- name: id
|
|
||||||
in: query
|
|
||||||
required: false
|
|
||||||
description: Rather than supplying a query, you can specify a speicific id to get data back on a lookup field.
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
get:
|
get:
|
||||||
operationId: crc.api.workflow.lookup
|
operationId: crc.api.workflow.lookup
|
||||||
|
|
|
@ -198,7 +198,7 @@ def delete_workflow_spec_category(cat_id):
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
def lookup(workflow_id, field_id, query=None, limit=10, id=None):
|
def lookup(workflow_id, field_id, query=None, value=None, limit=10):
|
||||||
"""
|
"""
|
||||||
given a field in a task, attempts to find the lookup table or function associated
|
given a field in a task, attempts to find the lookup table or function associated
|
||||||
with that field and runs a full-text query against it to locate the values and
|
with that field and runs a full-text query against it to locate the values and
|
||||||
|
@ -206,7 +206,7 @@ def lookup(workflow_id, field_id, query=None, limit=10, id=None):
|
||||||
Tries to be fast, but first runs will be very slow.
|
Tries to be fast, but first runs will be very slow.
|
||||||
"""
|
"""
|
||||||
workflow = session.query(WorkflowModel).filter(WorkflowModel.id == workflow_id).first()
|
workflow = session.query(WorkflowModel).filter(WorkflowModel.id == workflow_id).first()
|
||||||
lookup_data = LookupService.lookup(workflow, field_id, query, limit, id)
|
lookup_data = LookupService.lookup(workflow, field_id, query, value, limit)
|
||||||
return LookupDataSchema(many=True).dump(lookup_data)
|
return LookupDataSchema(many=True).dump(lookup_data)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,7 @@ class LookupDataSchema(SQLAlchemyAutoSchema):
|
||||||
load_instance = True
|
load_instance = True
|
||||||
include_relationships = False
|
include_relationships = False
|
||||||
include_fk = False # Includes foreign keys
|
include_fk = False # Includes foreign keys
|
||||||
|
exclude = ['id'] # Do not include the id field, it should never be used via the API.
|
||||||
|
|
||||||
|
|
||||||
class SimpleFileSchema(ma.Schema):
|
class SimpleFileSchema(ma.Schema):
|
||||||
|
|
|
@ -63,14 +63,14 @@ class LookupService(object):
|
||||||
return lookup_model
|
return lookup_model
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def lookup(workflow, field_id, query, limit, id = None):
|
def lookup(workflow, field_id, query, value, limit):
|
||||||
|
|
||||||
lookup_model = LookupService.__get_lookup_model(workflow, field_id)
|
lookup_model = LookupService.__get_lookup_model(workflow, field_id)
|
||||||
|
|
||||||
if lookup_model.is_ldap:
|
if lookup_model.is_ldap:
|
||||||
return LookupService._run_ldap_query(query, limit)
|
return LookupService._run_ldap_query(query, limit)
|
||||||
else:
|
else:
|
||||||
return LookupService._run_lookup_query(lookup_model, query, limit, id)
|
return LookupService._run_lookup_query(lookup_model, query, value, limit)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -157,10 +157,10 @@ class LookupService(object):
|
||||||
return lookup_model
|
return lookup_model
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _run_lookup_query(lookup_file_model, query, limit, lookup_id):
|
def _run_lookup_query(lookup_file_model, query, value, limit):
|
||||||
db_query = LookupDataModel.query.filter(LookupDataModel.lookup_file_model == lookup_file_model)
|
db_query = LookupDataModel.query.filter(LookupDataModel.lookup_file_model == lookup_file_model)
|
||||||
if lookup_id is not None: # Then just find the model with that id.
|
if value is not None: # Then just find the model with that value
|
||||||
db_query = db_query.filter(LookupDataModel.id == lookup_id)
|
db_query = db_query.filter(LookupDataModel.value == value)
|
||||||
else:
|
else:
|
||||||
# Build a full text query that takes all the terms provided and executes each term as a prefix query, and
|
# Build a full text query that takes all the terms provided and executes each term as a prefix query, and
|
||||||
# OR's those queries together. The order of the results is handled as a standard "Like" on the original
|
# OR's those queries together. The order of the results is handled as a standard "Like" on the original
|
||||||
|
|
|
@ -357,15 +357,36 @@ class TestTasksApi(BaseTest):
|
||||||
self.assert_success(rv)
|
self.assert_success(rv)
|
||||||
results = json.loads(rv.get_data(as_text=True))
|
results = json.loads(rv.get_data(as_text=True))
|
||||||
self.assertEqual(5, len(results))
|
self.assertEqual(5, len(results))
|
||||||
rv = self.app.get('/v1.0/workflow/%i/lookup/%s?id=%i' %
|
rv = self.app.get('/v1.0/workflow/%i/lookup/%s?value=%s' %
|
||||||
(workflow.id, field_id, results[0]['id']), # All records with a word that starts with 'c'
|
(workflow.id, field_id, results[0]['value']), # All records with a word that starts with 'c'
|
||||||
headers=self.logged_in_headers(),
|
headers=self.logged_in_headers(),
|
||||||
content_type="application/json")
|
content_type="application/json")
|
||||||
results = json.loads(rv.get_data(as_text=True))
|
results = json.loads(rv.get_data(as_text=True))
|
||||||
self.assertEqual(1, len(results))
|
self.assertEqual(1, len(results))
|
||||||
self.assertIsInstance(results[0]['data'], dict)
|
self.assertIsInstance(results[0]['data'], dict)
|
||||||
|
self.assertNotIn('id', results[0], "Don't include the internal id, that can be very confusing, and should not be used.")
|
||||||
|
|
||||||
|
def test_lookup_endpoint_also_works_for_enum(self):
|
||||||
|
# Naming here get's a little confusing. fields can be marked as enum or autocomplete.
|
||||||
|
# In the event of an auto-complete it's a type-ahead search field, for an enum the
|
||||||
|
# the key/values from the spreadsheet are added directly to the form and it shows up as
|
||||||
|
# a dropdown. This tests the case of wanting to get additional data when a user selects
|
||||||
|
# something from a drodown.
|
||||||
|
self.load_example_data()
|
||||||
|
workflow = self.create_workflow('enum_options_from_file')
|
||||||
|
# get the first form in the two form workflow.
|
||||||
|
workflow = self.get_workflow_api(workflow)
|
||||||
|
task = workflow.next_task
|
||||||
|
field_id = task.form['fields'][0]['id']
|
||||||
|
option_id = task.form['fields'][0]['options'][0]['id']
|
||||||
|
rv = self.app.get('/v1.0/workflow/%i/lookup/%s?value=%s' %
|
||||||
|
(workflow.id, field_id, option_id), # All records with a word that starts with 'c'
|
||||||
|
headers=self.logged_in_headers(),
|
||||||
|
content_type="application/json")
|
||||||
|
self.assert_success(rv)
|
||||||
|
results = json.loads(rv.get_data(as_text=True))
|
||||||
|
self.assertEqual(1, len(results))
|
||||||
|
self.assertIsInstance(results[0]['data'], dict)
|
||||||
|
|
||||||
def test_lookup_endpoint_for_task_ldap_field_lookup(self):
|
def test_lookup_endpoint_for_task_ldap_field_lookup(self):
|
||||||
self.load_example_data()
|
self.load_example_data()
|
||||||
|
|
Loading…
Reference in New Issue