2014-02-26 16 views
11

Ich bin völlig neu bei AJAX. Ich bin vertraut mit HTML/CSS, jQuery und Anfänger bei GAE und Python.Wie verwende ich AJAX mit Google App Engine (Python)

Um zu verstehen, wie AJAX funktioniert, würde ich gerne wissen, wie AJAX (tatsächlicher Code) in diesem Beispiel unten verwendet werden könnte. Lassen Sie sich ein reddit ähnliches Beispiel verwenden, wo Abstimmung Höhen/Tiefen ajaxified sind:

Hier ist die Geschichte Art:

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

Die HTML würde wie folgt aussehen:

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

Wie funktioniert AJAX fit hier drin?

Antwort

26

Ok Sir hier gehen wir ... Eine einfache App mit einer Geschichte und unendlich Stimmen ... ;-)

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()}))) 

und schließlich

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> 

montieren, lesen Sie es simpl e genug und lauf. Wenn Sie ein funktionierendes git Beispiel brauchen, kommentieren Sie einfach.

githublink (wie aus den Kommentaren)

+0

Wow! Dies ist ein erstaunlicher Aufwand in Ihrer Antwort, @JimmyKane gewidmet. Ich brauche etwas Zeit, um das zu durchbrechen. Wenn es kein Problem ist, würde mir die funktionierende Git-Version nichts ausmachen. Ich danke dir sehr. – puoyaahhh

+2

@haopei Sorry, ich habe dich vergessen. Hier gehts https://github.com/jimmykane/gae-voting-ajax-example. Ich hoffe du stierst es ;-) –

+1

Nochmals vielen Dank, @Jimmy Kane. – puoyaahhh

0

Hier ist ein kleiner prototype Web-App auf GitHub zu testen, wie Fehlermeldungen in HTML-Formularen mit AJAX, Python und Google App Engine zu handhaben. Es wird einen Ausgangspunkt geben, um zu sehen, wie diese drei Teile der Technologie ineinander greifen.Sie können diese "App" testen auf https://ajax-prototype.appspot.com/

Hier ist, wie es auf der Client-Seite funktioniert:

  • Diese htlm form submission verwendet wird:

    <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> 
    

  • Es wird triggert die JavaScript functionajaxScript:

    function ajaxScript() { 
        var input = $("#input").val(); 
        $.ajax({ 
         type: "POST", 
         url: "/", 
         data: JSON.stringify({ 
          "name": input 
         }), 
         dataType: "json" 
        }) 
         .done(function(jsonResponse) { 
          $("#error").html(jsonResponse.message); 
         }); 
    } 
    
  • Die Methode jQuery .ajax() verarbeitet die Anforderung, während die .done()-Methode eventuell die Antwort verarbeitet, die sie vom Server erhält.

Auf der Server-Seite:

  • Die main.py Datei übernimmt die Server-Seite des Unternehmens unseres mit handler classAjaxHandler, die von der GAE builtin-Klasse erbt webapp2.RequestHandler

  • Innerhalb dieses Klasse behandelt die post Methode die AJAX-Anforderung:

    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 \ 
             a-z, A-Z, 0-9, underscores \ 
             and hyphens." 
        else: 
         message = "Congrats!" 
    
        self.response.write(json.dumps({"message": message})) 
    
  • Grundsätzlich sind die handlichen json Module stellen die zwei Schlüssel Python Bestandteile

    • json.loads verarbeitet die Daten, die der Browser an den Server sendet.
    • verarbeitet die vom Server als Reaktion auf die Anforderung des Browsers gesendeten Daten.
    • Das self.request.body Argument von json.loads ist das einzige weniger geläufige Stück GAE, das in dem Prozess verwendet wird, da es für die Aufgabe spezifisch ist. Wie der Name schon andeutet, erhält er den Body von der Ajax-Anfrage, die vom Client gesendet wurde.