Comment utiliser AJAX avec Google App Engine (Python)

Je suis complètement novice chez AJAX. Je suis familier avec HTML / CSS, jQuery et débutant chez GAE et Python.

Dans un effort pour comprendre comment AJAX fonctionne, j'aimerais savoir comment AJAX pourrait être utilisé (code réel) dans cet exemple ci-dessous. Utilisons un exemple de type reddit où les hauts et les bas du vote sont ajaxified:

Voici le type d'histoire:

class Story(ndb.Model): title = ndb.StringProperty(required = True) vote_count = ndb.IntegerProperty(default = 0) 

Le HTML ressemblerait à ceci:

 <h2>{{story.title}}</h2> <div> {{story.vote_count}} | <a href="#">Vote Up Story</a> </div> 

Comment AJAX s'intègre-t-il ici?

Ok Monsieur ici, nous allons … Une application simple avec une histoire et des votes infinis … 😉

app.yaml

 application: anotherappname version: 1 runtime: python27 api_version: 1 threadsafe: true default_expiration: "0d 0h 5m" libraries: - name: jinja2 version: latest - name: webapp2 version: latest handlers: - url: .* script: main.app 

main.py

 import logging from controllers import server from config import config import webapp2 app = webapp2.WSGIApplication([ # Essential handlers ('/', server.RootPage), ('/vote/', server.VoteHandler) ],debug=True, config=config.config) # Extra Hanlder like 404 500 etc def handle_404(request, response, exception): logging.exception(exception) response.write('Oops! Naughty Mr. Jiggles (This is a 404)') response.set_status(404) app.error_handlers[404] = handle_404 

models/story.py

 from google.appengine.ext import ndb class Story(ndb.Model): title = ndb.StringProperty(required=True) vote_count = ndb.IntegerProperty(default = 0) 

controllers/server.py

 import os import re import logging import config import json import webapp2 import jinja2 from google.appengine.ext import ndb from models.story import Story class RootPage(webapp2.RequestHandler): def get(self): story = Story.get_or_insert('Some id or so', title='A voting story again...') jinja_environment = self.jinja_environment template = jinja_environment.get_template("/index.html") self.response.out.write(template.render({'story': story})) @property def jinja_environment(self): jinja_environment = jinja2.Environment( loader=jinja2.FileSystemLoader( os.path.join(os.path.dirname(__file__), '../views' )) ) return jinja_environment class VoteHandler(webapp2.RequestHandler): def post(self): logging.info(self.request.body) data = json.loads(self.request.body) story = ndb.Key(Story, data['storyKey']).get() story.vote_count += 1 story.put() self.response.out.write(json.dumps(({'story': story.to_dict()}))) 

et enfin

views/index.html

 <!DOCTYPE html> <html> <head> <base href="/"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> </head> <body> <h2>{{story.title}}</h2> <div> <span class="voteCount">{{story.vote_count}}</span> | <a href="javascript:VoteUp('{{story.key.id()}}');" >Vote Up Story</a> </div> <script> function VoteUp(storyKey){ $.ajax({ type: "POST", url: "/vote/", dataType: 'json', data: JSON.stringify({ "storyKey": storyKey}) }) .done(function( data ) { // check why I use done alert( "Vote Cast!!! Count is : " + data['story']['vote_count'] ); $('.voteCount').text(data['story']['vote_count']); }); }; </script> </body> </html> 

Assemblez, lisez, c'est assez simple et fonctionne. Si vous avez besoin d'un exemple de git de travail, veuillez simplement commenter.

Githublink (à partir des commentaires)

Voici un petit prototype d'application Web sur GitHub pour tester comment traiter les messages d'erreur dans des sous-formulaires HTML avec AJAX, Python et Google App Engine. Cela donnera un point de départ pour voir comment ces trois outils se combinent. Vous pouvez tester cette "application" sur https://ajax-prototype.appspot.com/

Voici comment cela fonctionne sur le côté client:

  • Cette présentation de formulaire htlm est utilisée:

     <form method="post" action="javascript:ajaxScript();"> <label>Please pick a name</label> <input id="input" type="text"> <input type="submit"> <div id="error" style="color:red"></div> 

  • Cela déclenchera la fonction JavaScript ajaxScript :

     function ajaxScript() { var input = $("#input").val(); $.ajax({ type: "POST", url: "/", data: JSON.stringify({ "name": input }), dataType: "json" }) .done(function(jsonResponse) { $("#error").html(jsonResponse.message); }); } 
  • La méthode .ajax() gère la requête tandis que la méthode .done() finira par gérer la réponse .done() partir du serveur.

Sur le côté serveur:

  • Le fichier principal.py prend en charge le côté serveur de l'entreprise en utilisant notre classe de gestionnaire AjaxHandler , qui hérite de la classe de classe GAE webapp2.RequestHandler

  • Dans cette classe, la méthode post traite la requête AJAX:

     def post(self): data = json.loads(self.request.body) username = data["name"] if not re.match(r"^[a-zA-Z0-9_-]{3,20}$", username): if len(username) < 3: message = "Your name must be at least 3 characters long." else: message = "Allowed characters are \ az, AZ, 0-9, underscores \ and hyphens." else: message = "Congrats!" self.response.write(json.dumps({"message": message})) 
  • Fondamentalement, le module json pratique fournit les deux principaux ingrédients Python

    • json.loads gère les données que le navigateur envoie au serveur.
    • json.dumps gère les données envoyées par le serveur en réponse à la demande du navigateur.
    • L'argument self.request.body de json.loads est la seule pièce de GAE moins commune qui est utilisée dans le processus, car elle est spécifique à la tâche. Comme son nom l'indique, il obtient le corps de la requête Ajax envoyée par le client.