380 likes | 399 Vues
Learn how to build a wiki using Google App Engine SDK. Download the SDK and follow step-by-step instructions to create a basic wiki, add markup, support revisions, display user pages, and fetch user feeds.
E N D
Googe App Engine Codelab Marzia Niccolai May 28-29, 2008
Step 1: Download the SDK • You must have Python 2.5 installed on your computer to use the App Engine SDK • http://code.google.com/p/googleappengine • Windows Installer • Mac App Engine Launcher • Zip Archive
Building a Wiki • Today we are going to build a wiki with Google App Engine • You can download the code from: • http://code.google.com/p/google-app-engine-codelab
Wiki Content • Step 1 - Basic Wiki • Step 2 - Wiki that uses Markup and displays the author • Step 3 - Wiki that supports revisions • Step 4 - Wiki that displays user page • Step 5 - Wiki that fetches user feeds During the Codelab, we will be going over steps 1&2 and building step 3
Wiki Data • To start with, we will have wiki pages with a title & a text body • With App Engine you store you data as objects called entities • Entities have 1 or more properties of supported data types
Data Types • IntegerProperty, FloatProperty, BooleanProperty • StringProperty, TextProperty • DateTimeProperty • ListProperty • ReferenceProperty, SelfReferenceProperty • UserProperty • BlobProperty • LinkProperty, EmailProperty • Other rich properties... • http://code.google.com/appengine/docs/datastore/typesandpropertyclasses.html
Defining a Model • Define your data models as a Python class • To create an entity use the class constructor • Call put() on the object to add it to the datastore
Defining the Wiki Model from google.appengine.ext import db class WikiPage(db.Model): title = db.StringProperty() body = db.TextProperty()
Create, Update, Delete • Once you have a data object (new or existing), calling put() writes that object to the datastore • object = WikiPage(title=my_title, body=my_body) • object.put() • To delete an object from the datastore, call delete() on the object # assume we have retrieved object object.delete()
Querying for Data • Google provides two methods for querying data • Today we’ll use GQL, a SQL-like query language • We also have a query interface, which you can read more about at: • http://code.google.com/appengine/docs
GQL • Google App Engine returns entire entities based on your queries • You can filter the data based on equalities and inequalities • You can order the data
Sample GQL Queries SELECT * FROM Person WHERE birth_year >= :min AND birth_year <= :max SELECT * FROM Person WHERE birth_year >= :min ORDER BY birth_year, last_name SELECT * FROM Person WHERE last_name = "Smith" AND height < 72 ORDER BY height DESC
Codelab: Building our wiki • Allow our users to: • View Wiki pages • Edit Wiki pages
app.yaml - Describing our App • The app.yaml specifies the application configuration for Google App Engine • Specify the application name and version: application: wiki version: 1
Wiki’s app.yaml • Specify the application’s script handlers: handlers: - url: /.* script: main.py
app.yaml: complete application: wiki version: 1 runtime: python api_version: 1 handlers: - url: .* script: main.py
WebApp Framework • WSGI framework for handling requests • Uses Request Handlers classes to serve pages • Returns entire output when handler exits (no streaming)
Wiki Page Handlers Requirements • View Wiki Pages (/view/WikiTopic) • Request page /view/WikiTopic • Directs you to the page on WikiTopic • Add/Edit Wiki Pages (/edit/WikiTopic) • Create pages that don’t exist • Edit existing pages
Define our View Handler • Redirect request from http://myapp.apppost.com/ to http://myapp.appspot.com/view/StartPage • When you request http://myapp.appspot.com/view/WikiPage • Display Content, if it exists! • Allow user to Add or Edit the Page
Define the Edit Handler • When the user requests /edit/WikiPage: • Give them form with a text box to enter content • Post the form to /save/WikiPage
Define the Save Handler • When the user posts a request to /save/WikiPage: • Get the body of the request • Create a data object • Store the object to the datastore • Redirect the user to /view/WikiPage
Wiki: Take 1 • http://localhost:8080/
Wiki: Take 1 Issues • We do no processing on the form input, and do no formatting • We are ignoring the Wiki author!
Wiki Take 2: Processing Form input • Use the ‘markdown’ third party library to allow formatting • Find WikiWords (words that are camel cased) and replace them with links
Wiki Take 2: Authors • Let people log in and out of our website • Only allow people who are logged in to edit pages • Store the author of the page
Wiki Take 2 in Action • http://localhost:8080
Wiki Take 3 - Revisions • You will be adding revision history • Each time someone edits the page, associate that revision as the current revision of the wiki page
Reference Properties • Enable 1:many, many:many entity relationships • Allows entity to store a reference to another entity
Using ReferenceProperty class Story(db.Model): story_text = db.TextProperty() class Comment(db.Model): story = db.ReferenceProperty(Story) comment_text = db.TextProperty() user = db.UserProperty()
Retrieve a Reference Property a_comment = Comment.gql(‘WHERE user = :1’, the_user).get() self.response.out.write(‘Our user commented on this story: %s’ % a_comment.story.story_text)
Back References a_story = Story.all().get() for a_comment in a_story.comment_set(): self.response.out.write(‘by:%s<br />%s<br />’ %(a_comment.user.nickname, a_comment.comment_text) )
ReferenceProperty & the Wiki • New object model for wiki take 3 class WikiUser(db.Model) • Store user information in an entity class WikiContent(db.Model) • Creates the parent wiki page class WikiRevision(db.Model) • Stores each revision of the Wiki Page
Wiki User • In the future we want our wiki page to have user profiles so we can create a user entity that stores information about our user: class WikiUser(db.Model): wiki_user = db.UserProperty() joined = db.DateTimeProperty(auto_now_add=True) wiki_user_picture = db.BlobProperty() user_feed = db.StringProperty()
Wiki Page class WikiContent(db.Model): title = db.StringProperty()
Wiki Revision class WikiRevision(db.Model): wiki_page = db.ReferenceProperty(WikiContent) revision_body = db.TextProperty(required=True) author = db.ReferenceProperty(WikiUser) created = db.DateTimeProperty(auto_now_add=True) version_number = db.IntegerProperty()
Now it’s your turn! • Using the model defined above, add support for revisions to our wiki! • We’ll be walking around to offer assistance as needed