#python #python_3x #django #google_maps_api
Задача состоит в том, чтобы сгенерить словарь из городов, такого типа:
{city: {'distance': '443 mi', 'duration': '9 hours 0 mins'}}
Вот модель:
@python_2_unicode_compatible
class Route(Base):
cities = models.ManyToManyField(City)
@cached_property
def cities_arrival_time(self, *args, **kwargs):
r = lambda: x, y: requests.get(
'https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&mode=driving&origins={}&destinations={}&key={}'.format(
x.name,
y.name,
settings.GEOPOSITION_GOOGLE_MAPS_API_KEY
)
)
После чего, нужно преобразовать duration таким образом, чтобы получить datetime
Проблема в том, что отправлять я не понимаю, как написать генератор, который будет
итерировать QuerySet исключая последний элемент.
Ответы
Ответ 1
Сделал совершенно иначе. import json import urllib import os import copy import ast import operator import requests DISTANCE_MATRIX_URL = "http://maps.googleapis.com/maps/api/distancematrix/" class DM(object): def __init__(self, api_key=None, url=DISTANCE_MATRIX_URL): self.api_key = api_key self.url = url self.response = '' self.dict_response = {'distance': {'value': {}, 'text': {}, }, 'duration': {'value': {}, 'text': {}, }, } self.origins = '' self.destinations = '' def make_request(self, origins, destinations, mode='driving'): data = {} self.origins = [origins] if type(origins) == str else origins self.destinations = [destinations] if type(destinations) == str else destinations data['origins'] = origins if type(origins) == str else '|'.join(origins) data['destinations'] = destinations if type(destinations) == str else '|'.join(destinations) data['mode'] = mode url_values = urllib.parse.urlencode(data) output_format = 'json' url = os.path.join(self.url, output_format) self.response = ast.literal_eval((urllib.request.urlopen(url + '?' + url_values).read()).decode("utf-8"))['rows'] self.dict_response = {'distance': {'value': {}, 'text': {}, }, # Reset temporary dict 'duration': {'value': {}, 'text': {}, }, } def __get_response_element_data(self, key1, key2): if not self.dict_response[key1][key2]: l = self.response for i, orig in enumerate(self.origins): self.dict_response[key1][key2][orig] = {} for j, dest in enumerate(self.destinations): if l[i]['elements'][j]['status'] == 'OK': self.dict_response[key1][key2][orig][dest] = l[i]['elements'][j][key1][key2] else: self.dict_response[key1][key2][orig][dest] = l[i]['elements'][j]['status'] return self.dict_response[key1][key2] def get_distance_values(self): return self.__get_response_element_data('distance', 'value') def get_distance_texts(self): return self.__get_response_element_data('distance', 'text') def get_time_values(self): return self.__get_response_element_data('duration', 'value') def get_time_texts(self): return self.__get_response_element_data('duration', 'text') def get_closest_points(self, max_distance=None, num=10, origin_index=0, origin_raw=None): if not self.dict_response['distance']['value']: self.get_distance_values() if origin_raw: origin = copy.deepcopy(self.dict_response['distance']['value'][origin_raw]) else: origin = copy.deepcopy(self.dict_response['distance']['value'][self.origins[origin_index]]) tmp_origin = copy.deepcopy(origin) if max_distance: for k, v in tmp_origin.iteritems(): if v > max_distance: del(origin[k]) if origin: return sorted(origin.iteritems(), key=operator.itemgetter(1))[:num] Работает это так: a = DM() a.make_request(['Minsk'], ['Moscow']) # Отдаём один origin (точка, от которой считаем) и один destination (пункт назначения). Если хотим получить результат в текстовом формате (он менее точный), то делаем так: a.get_distance_texts() и получаем результат: {'Minsk': {'Moscow': '717 km'}} Если же, нужно посчитать расстояние между одним origin и несколькими destination, то делаем так: a.make_request(['Minsk'], ['Moscow', 'Sankt-Peterburg']) a.get_distance_texts() {'Minsk': {'Moscow': '717 km', 'Sankt-Peterburg': '795 km'}} В действительности, расстояние иное. Но разница между Москвой и СПб более-менее точная. Вот так получаем данные в метрах: a.get_distance_values() {'Minsk': {'Moscow': 717038, 'Sankt-Peterburg': 795481}} А вот так, получаем duration a.get_time_values() {'Minsk': {'Moscow': 28751, 'Sankt-Peterburg': 36415}} Точно так же, с текстовым отображением: a.get_time_texts() {'Minsk': {'Moscow': '7 hours 59 mins', 'Sankt-Peterburg': '10 hours 7 mins'}} Если же надо узнать про расстояние между несколькоими origins и destinations, то так: a.make_request(['Minsk', 'Moscow'], ['Moscow', 'Varshava']) a.get_distance_texts() {'Minsk': {'Moscow': '717 km', 'Varshava': '554 km'}, 'Moscow': {'Moscow': '1 m', 'Varshava': '1,264 km'}} А вот так: a.get_closest_points() Получаем список из кортежей, где первый элемент - пункт назначения, а второй - расстояние от первого origin [('Varshava', 553521), ('Moscow', 717038)]
Комментариев нет:
Отправить комментарий