1

я получил следующую GAE датастора модели (модели/location.py), которые я хочу, чтобы заполнить:Асинхронного место поиска на GAE/webapp2

from google.appengine.ext import db 
class Location(db.Model): 
    name = db.StringProperty(required=True) 
    country = db.StringProperty(required=False) 
    address = db.PostalAddressProperty(required=False) 
    coordinates = db.GeoPtProperty(required=False) 
    description = db.TextProperty(required=False) 

Для этого я создал класс LocationCreateHandler и функция _geocode (handlers/location.py):

from google.appengine.ext import db 
from google.appengine.api import urlfetch 
from webapp2_extras import json 
import urllib 
from handlers import BaseHandler 
from models.location import Location 
import logging 

class LocationCreateHandler(BaseHandler): 
    def post(self): 
     name = self.request.get("name") 
     country = self.request.get("country") 
     address = self.request.get("address") 
     coordinates = _geocode(self, address) 
     description = self.request.get("description") 
     newLocation = Location(name=name, country=country, address=address, coordinates=coordinates, description=description) 
     newLocation.put() 
     return self.redirect("/location/create") 

    def get(self): 
     self.render_response("location/create.html") 

def _geocode(self, address): 
    try: 
     logging.info("Geocode address: %s", address) 
     parameter = {'address': address.encode('utf-8'), 'sensor': 'false'} 
     payload = urllib.urlencode(parameter) 
     url = ('https://maps.googleapis.com/maps/api/geocode/json?%s' % payload) 
     logging.info("Geocode URL: %s", url) 
     result = urlfetch.fetch(url) 
     jsondata = json.decode(result.content) 
     location = jsondata['results'][0]['geometry']['location'] 
     coordinates = '%s,%s' % (location['lat'], location['lng']) 
     logging.info("Geocode coordinates: %s", coordinates) 
     return coordinates 
    except: 
     return "0.0,0.0" 

Как бы сделать это асинхронным? В настоящий момент пользователю придется подождать, пока поиск геокода не завершится. Как только я получу эту работу, я также планирую использовать _geocode() после обновления записи местоположения.

Мне еще нужно выяснить часть _geocode после «result =», кажется, там ошибка, так как я всегда получаю 0.0,0.0.

-Luca.

ответ

1

Похоже, что это полезно для task queues. Когда POST прибывает, откройте задачу, передав ей все параметры для объекта Location. Затем вы можете завершить запрос и сразу же вернуться к клиенту. Задача может вызвать _geocode, а затем создать объект Location со всеми данными.

Или, если вам нужно создать объект Location в обработчике запроса по какой-либо причине, вы можете сделать это в обработчике POST и передать ключ нового объекта в задачу. Когда задача завершается, она может получить объект и обновить его с помощью координат.

Кроме того, чтобы помочь определить, почему ваш UrlFetch не работает, вот способ войти исключение при этом ловя:

import traceback 
try: 
    ... 
except: 
    logging.exception(traceback.print_exc()) 
1

Спасибо Джейми

я в настоящее время реализовать GeocodeWorker (работники/googleapis.py) с использованием очередей задач:

from handlers import BaseHandler 
import urllib 
import logging 
from google.appengine.api import urlfetch 
from google.appengine.ext import db 
from webapp2_extras import json 
from models.location import Location 

class GeocodeWorker(BaseHandler): 
    def post(self): 
     address = self.request.get('address') 
     logging.info("Geocode address: %s", address) 
     parameter = {'address': address.encode('utf-8'), 'sensor': 'false'} 
     url = ('https://maps.googleapis.com/maps/api/geocode/json?%s' % urllib.urlencode(parameter)) 
     logging.info("Geocode URL: %s", url) 
     result = urlfetch.fetch(url) 
     JSONData = json.decode(result.content) 
     location = JSONData['results'][0]['geometry']['location'] 
     coordinates = '%s,%s' % (location['lat'], location['lng']) 
     logging.info("Geocode coordinates: %s", coordinates) 
     key = self.request.get('key') 
     logging.info("Geocode key: %s", key) 
     existingLocation = Location.get(db.Key(key)) 
     existingLocation.coordinates = coordinates 
     existingLocation.put() 

Я также изменил мой обработчик местоположения (обработчики/location.py) для вызова работника:

from google.appengine.api import taskqueue 
from webapp2 import uri_for 

class LocationCreateHandler(BaseHandler): 
    def get(self): 
     self.render_response('location/create.html') 
    def post(self): 
     name = self.request.get('name') 
     country = self.request.get('country') 
     address = self.request.get('address') 
     description = self.request.get('description') 
     newLocation = Location(name=name, country=country, address=address, description=description) 
     key = newLocation.put() 
     params = {'key': key, 'address': address} 
     taskqueue.add(url=uri_for('googleapis-geocode'), queue_name='googleapis', name=('googleapis-geocode-%s' % key), params=params) 
     return self.redirect('/location/create') 

Я также создал файл queue.yaml, определяющий очередь googleapis. Также я удалил попытку: кроме: part. Очередь Google автоматически повторит операцию и завершит работу через определенное время.

Вы видите какие-либо области улучшений?

-Luca.

+0

Да, это именно то, что я имел в виду. Выглядит отлично! –

+0

Извините, что сначала я этого не видел. Stack Overflow не уведомляет вас, если кто-то отправляет другой ответ на вопрос, на который вы ответили. Могли бы вы принять/поддержать мой ответ, если он сработает для вас? –

+0

Привет, Джейми, я принял ваш ответ. Он делает именно то, что должен делать. Большое спасибо! – decurgia