126 |
126 |
return tupled_items
|
127 |
127 |
|
128 |
128 |
|
129 |
|
def request_json_items(url, data_source):
|
|
129 |
def get_json_from_url(url, data_source):
|
130 |
130 |
url = sign_url_auto_orig(url)
|
131 |
131 |
data_key = data_source.get('data_attribute') or 'data'
|
|
132 |
geojson = data_source.get('type') == 'geojson'
|
132 |
133 |
try:
|
133 |
134 |
entries = misc.json_loads(misc.urlopen(url).read())
|
134 |
135 |
if not isinstance(entries, dict):
|
135 |
136 |
raise ValueError('not a json dict')
|
136 |
137 |
if entries.get('err') not in (None, 0, "0"):
|
137 |
138 |
raise ValueError('err %s' % entries['err'])
|
138 |
|
if not isinstance(entries.get(data_key), list):
|
139 |
|
raise ValueError('not a json dict with a %s list attribute' % data_key)
|
|
139 |
if geojson:
|
|
140 |
if not isinstance(entries.get('features'), list):
|
|
141 |
raise ValueError('bad geojson format')
|
|
142 |
else:
|
|
143 |
if not isinstance(entries.get(data_key), list):
|
|
144 |
raise ValueError('not a json dict with a %s list attribute' % data_key)
|
140 |
145 |
except misc.ConnectionError as e:
|
141 |
146 |
get_logger().warning('Error loading JSON data source (%s)' % str(e))
|
142 |
147 |
return None
|
143 |
148 |
except (ValueError, TypeError) as e:
|
144 |
149 |
get_logger().warning('Error reading JSON data source output (%s)' % str(e))
|
145 |
150 |
return None
|
146 |
|
items = []
|
|
151 |
return entries
|
|
152 |
|
|
153 |
|
|
154 |
def request_json_items(url, data_source):
|
|
155 |
entries = get_json_from_url(url, data_source)
|
|
156 |
if entries is None:
|
|
157 |
return None
|
|
158 |
data_key = data_source.get('data_attribute') or 'data'
|
147 |
159 |
id_attribute = data_source.get('id_attribute') or 'id'
|
148 |
160 |
text_attribute = data_source.get('text_attribute') or 'text'
|
|
161 |
items = []
|
149 |
162 |
for item in entries.get(data_key):
|
150 |
163 |
# skip malformed items
|
151 |
164 |
if not isinstance(item, dict):
|
... | ... | |
162 |
175 |
|
163 |
176 |
|
164 |
177 |
def request_geojson_items(url, data_source):
|
165 |
|
url = sign_url_auto_orig(url)
|
166 |
|
try:
|
167 |
|
entries = misc.json_loads(misc.urlopen(url).read())
|
168 |
|
if not isinstance(entries, dict):
|
169 |
|
raise ValueError('not a json dict')
|
170 |
|
if entries.get('err') not in (None, 0, "0"):
|
171 |
|
raise ValueError('err %s' % entries['err'])
|
172 |
|
if not isinstance(entries.get('features'), list):
|
173 |
|
raise ValueError('bad geojson format')
|
174 |
|
except misc.ConnectionError as e:
|
175 |
|
get_logger().warning('Error loading GeoJSON data source (%s)' % str(e))
|
176 |
|
return None
|
177 |
|
except (ValueError, TypeError) as e:
|
178 |
|
get_logger().warning('Error reading GeoJSON data source output (%s)' % str(e))
|
|
178 |
entries = get_json_from_url(url, data_source)
|
|
179 |
if entries is None:
|
179 |
180 |
return None
|
180 |
181 |
items = []
|
181 |
182 |
id_property = data_source.get('id_property') or 'id'
|
... | ... | |
306 |
307 |
return NamedDataSource.get_by_slug(ds_type).data_source
|
307 |
308 |
|
308 |
309 |
|
309 |
|
def get_object(data_source):
|
|
310 |
def get_object(data_source, ignore_errors=True):
|
310 |
311 |
if not data_source:
|
311 |
312 |
return None
|
312 |
313 |
ds_type = data_source.get('type')
|
... | ... | |
320 |
321 |
named_data_source = NamedDataSource()
|
321 |
322 |
named_data_source.data_source = data_source
|
322 |
323 |
return named_data_source
|
323 |
|
return NamedDataSource.get_by_slug(ds_type)
|
|
324 |
return NamedDataSource.get_by_slug(ds_type, ignore_errors=ignore_errors)
|
324 |
325 |
|
325 |
326 |
|
326 |
327 |
class NamedDataSource(XmlStorableObject):
|
... | ... | |
444 |
445 |
}
|
445 |
446 |
|
446 |
447 |
@classmethod
|
447 |
|
def get_by_slug(cls, slug):
|
|
448 |
def get_by_slug(cls, slug, ignore_errors=True):
|
448 |
449 |
objects = [x for x in cls.select() if x.slug == slug]
|
449 |
450 |
if objects:
|
450 |
451 |
return objects[0]
|
|
452 |
if not ignore_errors:
|
|
453 |
raise KeyError(slug)
|
451 |
454 |
get_logger().warning("data source '%s' does not exist" % slug)
|
452 |
455 |
return StubNamedDataSource(name=slug)
|
453 |
456 |
|
... | ... | |
499 |
502 |
}))
|
500 |
503 |
return None
|
501 |
504 |
|
|
505 |
def get_geojson_url(self):
|
|
506 |
assert self.type == 'geojson'
|
|
507 |
return '/api/geojson/%s' % self.slug
|
|
508 |
|
|
509 |
def get_geojson_data(self):
|
|
510 |
url = self.data_source.get('value').strip()
|
|
511 |
if Template.is_template_string(url):
|
|
512 |
vars = get_publisher().substitutions.get_context_variables(mode='lazy')
|
|
513 |
url = get_variadic_url(url, vars)
|
|
514 |
|
|
515 |
request = get_request()
|
|
516 |
if hasattr(request, 'datasources_cache') and url in request.datasources_cache:
|
|
517 |
return request.datasources_cache[url]
|
|
518 |
|
|
519 |
cache_duration = 0
|
|
520 |
if self.cache_duration:
|
|
521 |
cache_duration = int(self.cache_duration)
|
|
522 |
|
|
523 |
if cache_duration:
|
|
524 |
cache_key = 'geojson-data-source-%s' % force_str(hashlib.md5(force_bytes(url)).hexdigest())
|
|
525 |
from django.core.cache import cache
|
|
526 |
data = cache.get(cache_key)
|
|
527 |
if data is not None:
|
|
528 |
return data
|
|
529 |
|
|
530 |
data = get_json_from_url(url, self.data_source)
|
|
531 |
id_property = self.id_property or 'id'
|
|
532 |
label_template_property = self.label_template_property or '{{ text }}'
|
|
533 |
|
|
534 |
for feature in data['features']:
|
|
535 |
feature['properties']['_id'] = feature['properties'][id_property]
|
|
536 |
try:
|
|
537 |
feature['properties']['_text'] = Template(
|
|
538 |
label_template_property).render(feature['properties'])
|
|
539 |
except (TemplateSyntaxError, VariableDoesNotExist):
|
|
540 |
pass
|
|
541 |
if not feature['properties'].get('_text'):
|
|
542 |
feature['properties']['_text'] = feature['properties']['_id']
|
|
543 |
|
|
544 |
if hasattr(request, 'datasources_cache'):
|
|
545 |
request.datasources_cache[url] = data
|
|
546 |
if cache_duration:
|
|
547 |
cache.set(cache_key, data, cache_duration)
|
|
548 |
|
|
549 |
return data
|
|
550 |
|
502 |
551 |
def get_value_by_id(self, param_name, param_value):
|
503 |
552 |
url = self.data_source.get('value').strip()
|
504 |
553 |
if Template.is_template_string(url):
|
... | ... | |
562 |
611 |
elif self.type == 'json' and self.id_parameter:
|
563 |
612 |
value = self.get_value_by_id(self.id_parameter, option_id)
|
564 |
613 |
else:
|
565 |
|
structured_items = get_structured_items(self.data_source, mode='lazy')
|
|
614 |
structured_items = get_structured_items(self.extended_data_source, mode='lazy')
|
566 |
615 |
for item in structured_items:
|
567 |
616 |
if str(item['id']) == str(option_id):
|
568 |
617 |
value = item
|
569 |
|
-
|