Получение очереди задач pull для работы с cron

Я новичок в python и GAE, и я пытался научиться работать с очередями задач, cron и хранилищем данных для моего собственного проекта на примерах, но мне совсем не повезло. Я пытаюсь изменить код Votelator из этого обучающего видео Google Developers на YouTube: http://www.youtube.com/watch?v=AM0ZPO7-lcE, работающий здесь: http://voterlator.appspot.com/

Я понял, что код неполный, поэтому решил попытаться выяснить, чего не хватает. Я сделал некоторые замены (например, языки программирования теперь являются молочными продуктами). Есть несколько вещей, которые не проработаны в коде учебника. Например, переменная LANGUAGES нигде не указана. Мне непонятно, как модель данных извлекает значения для языков из формы и использует их в качестве ключей.

Я не могу понять, почему это не работает. Я оставил часть кода, который пытался заставить его работать, и закомментировал его.

Вот приложение.yaml:

application: voting
version: 1
runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /static/css
  static_dir: static/css

- url: /static/css/sunny
  static_dir: static/css/sunny

- url: /static/js
  static_dir: static/js

- url: /cron/tally
  script: main.app

- url: /.*
  script: main.app

Вот cron.yaml:

cron:
- description: vote tallying worker
  url: /cron/tally
  schedule: every 1 minutes

Это очередь.yaml

total_storage_limit: 120M
queue:
- name: votes
  mode: pull

Это main.py

import webapp2
from google.appengine.ext import db
from google.appengine.api import taskqueue
import os
import jinja2

jinja_environment = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))

class Tally(db.Model):
    """Counting model"""

    count = db.IntegerProperty(default=0, required=True)
    #key_name = ['Milk', 'Butter', 'Cheese'] #added
    #key_name = db.StringProperty(choices=set(['Milk', 'Butter', 'Cheese'])) #added
    cls = ['Milk', 'Butter', 'Cheese'] #added

    @classmethod
    def increment_by(cls, key_name, count):
        """Increases a tally's count. Should be run in a transaction."One tally for each language"""
        """The key_name is going to be the language name"""
        """There's a convenience method there that actually will update the count"""

        tally = cls.get_by_key_name(key_name)
        if tally is None:
            tally = cls(key_name=key_name)
        tally.count += count
        tally.put()
    #db.run_in_transaction(increment_by, key_name, count) #added
        #db.run_in_transaction(cls, key_name, count) #added

    #db.run_in_transaction(Tally.increment_by, cls, count) #added

class VoteHandler(webapp2.RequestHandler):
    """Handles adding of vote tasks"""
    def get(self):
        """Displays the voting form"""


        tally_query = Tally.all() #added
        #tally_query = Tally.all(key_name)   #added  
        tallies = tally_query.fetch(3) #added

        urla = '_ah/admin/'
        url_admin = 'Admin'

        urlvh = '/'
        url_votehand = 'Votes'

        ugliest = self.request.get('ugliest')

        template_values = {
            'tallies': tallies, #added
            'ugliest': ugliest, #added               

            'url_admin': url_admin,
            'urla': urla,

            'urlvh': urlvh,
            'url_votehand': url_votehand,
        }
        template = jinja_environment.get_template('vote_handler.html')
        self.response.out.write(template.render(template_values))
    def post(self):
        """Adds to the votes queue if ugliest is valid. """

        LANGUAGES = ['Milk', 'Butter', 'Cheese'] #added: This is just a guess

        ugliest = self.request.get('ugliest')
        if ugliest and ugliest in LANGUAGES:  ### No variable specified for LANGUAGES
            q = taskqueue.Queue('votes')
            q.add(taskqueue.Task(payload=ugliest, method='PULL'))

        self.redirect('/')

    #db.run_in_transaction(Tally.increment_by(cls, key_name, count)) #added

class TallyHandler(webapp2.RequestHandler):
    def post(self):
        """Leases vote tasks, accumulates tallies and stores them"""
        q = taskqueue.Queue('votes')
        # Keep leasing tasks in a loop.
        while True:
            tasks = q.lease_tasks(300, 1000)
            if not tasks:
                return
            # accumulate tallies in memory
            tallies = {}
            for t in tasks:
                tallies[t.payload] = tallies.get(t.payload, 0) + 1
            self.store_tallies(tallies)
            q.delete_tasks(tasks)

app = webapp2.WSGIApplication([('/', VoteHandler),
                               ('/cron/tally', TallyHandler)], #called from cron, pulls votes from the queue and updating tallies
                          debug=True)



def main():
    app.run()

if __name__ == "__main__":
    main()

Это код формы в файле voice_handler.html:

<form action="/" method="post">
<input type="radio" name="ugliest" value="Milk" /> Milk<br>
<input type="radio" name="ugliest" value="Butter" /> Butter<br>
<input type="radio" name="ugliest" value="Cheese" /> Cheese
<br>
<div>
<input type="submit" value="Submit">
</div>
</form>

<div class="commentary">
    {% for tally in tallies %}
      {{ tally.count }}
    {% endfor %}
</div>

Я попытался заставить его отображать результаты чуть ниже формы.

В конечном итоге происходит то, что форма добавляет задачи в очередь, и в хранилище данных есть тип задачи, но в нем нет никаких сущностей. Я понятия не имею, что не так.


person 655321    schedule 28.01.2013    source источник


Ответы (1)


Метод «put» TallyHandler следует переименовать в «get». (Задание cron вызовет URL-адрес, используя HTTP-запрос GET.)

Обратите внимание, что задачи cron не запускаются автоматически в среде разработки, а только в рабочей среде. Используйте консоль администратора, чтобы вручную запустить задачу cron.

Необходимо определить метод store_tallies. Исходный код см. на странице http://google-app-engine-samples.googlecode.com/svn/trunk/voterlator/

Кстати, в app.yaml я бы рекомендовал ограничить доступ к вашим URL-адресам cron, используя

login: admin
person Eric Willigers    schedule 28.01.2013
comment
Спасибо!!! Я проверил код. Я знаю, что это не должно быть исчерпывающим учебным пособием, но в видео многого не хватает. Теперь это работает по большей части, за исключением того, что имена, за которые они голосуют, не отображаются в форме. Но я могу это понять. - person 655321; 29.01.2013