google app engine 9 ( user api )

import ก่อน

from google.appengine.api import users

เอา user ปัจจุบันมาโดย get_current_user()

user = users.get_current_user()

เราสามารถ print user.nickname() หรือ user.email() ได้

แล้ว users ยังมี method ไว้เอา login_url หรือ logout_url ออกมาด้วย
users.create_logout_url, users.create_login_url

if users.get_current_user():
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
else:
url = users.create_login_url(self.request.uri)
url_linktext = 'Login'

ดู user reference

Advertisements

google app engine 8 ( file upload )

ตัวอย่างเลยละกัน

<form action="." method="post" enctype="multipart/form-data">
<label>File: </label><input name="file" type="file"><br />
<input type="submit">
</form>

Server side:

class Image(db.Model):
name        = db.StringProperty()
content     = db.BlobProperty()

class UploadImage(webapp.RequestHandler):
def post(self):
if 'file' not in self.request.POST:
self.error(400)
self.response.out.write("file not specified!")
return

if (self.request.POST.get('file', None) is None or
not self.request.POST.get('file', None).filename):
self.error(400)
self.response.out.write("file not specified!")
return

file_data = self.request.POST.get('file').file.read()
file_name = self.request.POST.get('file').filename

im = Image()
im.name    = file_name
im.content = file_data
im.save()
self.response.out.write("image %r saved." % im.name)

.file.read() กัับ .filename

ตามนั้นแหละ

reference : http://popcnt.org/2008/05/google-app-engine-tips.html

google app engine 7 ( datastore )

เห็นเขาว่าเหมือน Django’s data modelling API แต่ว่า scalable กว่า

ก่อนอื่นต้อง import module db มาก่อน

from google.appengine.ext import db

จากนั้นประกาศโมเดล ลองเขียนหลายๆชนิดดังนี้

class Greeting(db.Model) :

author = db.UserProperty()                                # User
content = db.StringProperty(multiline=True)  # String ( multiline (optional) : this property can contain newline characters )

text = db.TextProperty() # long String
date = db.DateTimeProperty(auto_now_add=True) # DateTime ( auto_now_add=True : ใส่ค่า default เป็น now ถ้าไม่ได้กำหนดค่าให้มัน )

ดูชนิดได้ ตามนี้

อื่นๆ ดูได้จาก datastore reference

Create/Update

สมมติว่ามีหน้าฟอร์มโพสมาที่หน้านี้แล้ว

class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()

if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting<strong>.put()</strong> #  saves our new object to the datastore ถ้ามีอยู่แล้วจะ update มัน
self.redirect('/')

หรือจะเล่นแบบนี้เลยก็ได้ ง่ายดี

greeting = Greeting(author = users.get_current_user(), content = self.request.get('content'))

greeting.put()

select

greetings = Greeting.all()

จะ order หรือ where ก็ได้

greetings = Greeting.all()
greetings.filter("author =", users.get_current_user())

greetings.order("-date")

greetings_query.fetch(10)

หรือจะเอามายำๆอยู่บรรทัดเดียวกันก็ได้

greetings_query = Greeting.all().order('-date')
greetings = greetings_query.fetch(10)

จากนั้น

{% for greeting in greetings %}

{{ greeting.key.id }}  # คีย์ของแต่ละเรคอร์ด

{{ greeting.author }}
{{ greeting.content }}
{% endfor %}

count ได้ด้วยนะ

greetings.count()

greetings[0]

เรายังสามารถ get_by_id ได้ด้วย Greeting.get_by_id(greeting_id)

นอกจากนี้เรายังสามารถเขียน query ไปตรงๆ โดยใช้ gql ก็ได้

if users.get_current_user():
greetings = Greeting.gql("WHERE author = <strong>:1</strong> ORDER BY date DESC LIMIT 20",
users.get_current_user())

หรือ

greetings = Greeting.gql("WHERE author = <strong>:author</strong> ORDER BY date DESC",
author=users.get_current_user())

NOTE :

– สามารถจัดการ data ที่เก็บไว้แล้วได้จาก http://localhost:8080/_ah/admin/datastore

( Entity Kind คือ ชื่อ Object )

ซึ่งมี interactive console ไว้ให้เล่นด้วย เด็ดจริงๆ

ถ้าจะเล่นกับ Model ในนั้น ต้อง import มันเข้ามาก่อน

from main import Greeting

– ถ้าต้องการ Clear Development Server Datastore

ตอน start server

$ dev_appserver.py --clear_datastore helloworld/

– ปกติมันจะสร้าง datastore ไว้ใน temp ในเครื่องของเรา ถ้าไม่อยากให้มันหายไปตอนเรารีสตาร์ท ให้กำหนด

--datastore_path=Folder ตอน dev_appserver

google app engine 5 ( template variable )

{{ variable_name }}

มี Filter ให้ใช้เหมือน smarty เลยแหะ

{{ variable_name|escape|linebreaks }}
{% for greeting in greetings %}
{% if greeting.author %}
<strong>{{ greeting.author.nickname }}</strong> wrote:
{% else %}
An anonymous person wrote:
{% endif %}
{{ greeting.content|escape }}
{% endfor %}

google app engine 4 ( static file )

app.yaml ———————

application: dsin
version: 1
runtime: python
api_version: 1

handlers:
- url: /stylesheets
static_dir: stylesheets

- url: /.*
script: helloworld.py

file with a name ending in .css will be served with a MIME type of text/css. You can configure explicit MIME types with additional options.

the app.yaml reference

google app engine 3 ( Template )

google app engine สามารถใช้ template พวก EZT, Cheetah, ClearSilver, Quixote, and Django ได้

webapp module includes Django templating engine มาแล้ว ไม่จำเป็นต้อง bundle เพื่อใช้อีก

วิธีใช้คือ import template ก่อน

from google.appengine.ext.webapp import template

แล้วแทนที่จะ response.out.write เฉยๆ ก็ใส่เป็น template ไปซะ

ซึ่งเราสามารถ pass objects อะไรไปก็ได้ ( รวมทั้ง datastore model object ด้วย )

path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, {
'greetings': greetings,
'url': url,
'url_linktext': url_linktext,
}))

ดู the Django 0.96 template documentation

google app engine 2 ( main.py )

จริงๆ main.py เป็น print print โง่ๆเลยก็ได้

print 'Content-Type: text/plain'
print ''
print 'Hello, world!'

แต่ใน new_project_template/main.py ทำงานโดยใช้ webapp framework แบบนี้

import wsgiref.handlers

from google.appengine.ext import webapp

class AddPage(webapp.RequestHandler):

def post(self):

...

class MainHandler(webapp.RequestHandler):

def get(self):

self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Hello world!')

def main():
application = webapp.WSGIApplication([('/', MainHandler), ('/add',AddPage)],
debug=True)
wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
main()

ซึ่งผลลัพธ์ก็คือคำว่า  Hello world! เหมือนกัน

NOTE :

– เราสามารถ escape HTML special char ได้โดยใช้โมดูล cgi ตามนี้
cgi.escape

self.response.out.write(cgi.escape(self.request.get('content')))

– [(‘/’, MainHandler)] เป็นการ map URL

นอกจากนี้ยังสามารถใส่เป็น regex ได้ด้วยดังนี้ (r‘/blog/(.*)/(.*)’, CommentView)

ซึ่งจะต้องรับ parameter มาจาก method

def get(self, blog_id, comment_id): # รับ parameter สองตัว

– import wsgiref.handlers : เป็นการใช้ wsgiref เพื่อรัน WSGIApplication โดยใช้ CGI adaptor ดูรายละเอียดจาก wsgiref module documentation

– debug=True : จะมีการ print stack traces ถ้ามี error หรือ uncaught exception
– ดู webapp reference ที่นี่

เกี่ยวกับ webapp framework นิดนึง

google app engine สนับสนุน framework พวก
Django, CherryPy, Pylons, และ web.py

แต่ของ google ชื่อ webapp framework

* one or more RequestHandler classes ประมวลผล requests และสร้าง responses
* a WSGIApplication instance that routes incoming requests to handlers based on the URL
* a main routine that runs the WSGIApplication using a CGI adaptor

basic google app engine 1

หลังจาก ร่างฉบับเน่าๆ ไว้ที่ blogspot ด้วยความหงุดหงิดกับ text editor ห่วยๆ ของมัน

เลยคิดว่าย้ายมาไว้นี่ดีกว่า

เริ่มแรกมาโหลด app engine มาจากเวปของ google

extract มันซะ แล้วสังเกตว่า มันจะมีโฟลเดอร์ชื่อว่า new_project_template อยู่

ก็อบโฟลเดอร์แมร่งเลย แล้วเปลี่ยนเป็นชื่อโฟลเดอร์ของเรา

ในนั้นจะมีไฟล์อยู่สามไฟล์ app.yaml, index.yaml, main.py

ใน app.yaml เข้าไปเปลี่ยนชื่อ application เป็น application-id ที่เรา register ไว้กับ http://appengine.google.com

เช่น ถ้า dsin.appspot.com ก็เปลี่ยนเป็น

application: dsin
version: 1
runtime: python
api_version: 1

handlers:
- url: .*
  script: main.py

ไอ้ตรง handlers มันหมายความว่า ทุก URL (*)  ให้ไปเรียก main.py ให้หมด

NOTE

– มันมีเคาะวรรคสองที ก่อนหน้า script:

– ระวังชื่อไฟล์ main.py นี้มัน case-sensitive น้ะจ้ะ

– format นี้เขาเรียกว่า yaml ดูรายละเอียดได้จากเวปของ YAML

– ดูวิธี config app.yaml เพิ่มเติมได้ ที่นี่

เวลารันเพื่อเทส

$ /media/disk/google_appengine/dev_appserver.py [folder]

เรียกจาก http://localhost:8080 ได้เลย

NOTE : default port คือ 8080 นะ

ถ้าต้องการเปลี่ยน port

$ /media/disk/google_appengine/dev_appserver.py --port=9999 [folder]

UPLOAD APP TO SERVER

$ /media/app/google_appengine/appcfg.py update [folder]/