15.1K
dev_appserver.py .터미널 윈도우에 애플리케이션을 띄워놓으면 소스코드를 변경했을 때 그 내용이 자동으로 반영된다. 각자가 선호하는 에디터로 change.py를 다른 창으로 열어보면, 이 파일이 애플리케이션의 대부분을 차지함을 알 수 있다. 이 파일의 코드는 다음과 같다.
#!/usr/bin/env python2.5
#Noah Gift
import decimal
import wsgiref.handlers
import os
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp import template
class ChangeModel(db.Model):
user = db.UserProperty()
input = db.IntegerProperty()
date = db.DateTimeProperty(auto_now_add=True)
class MainPage(webapp.RequestHandler):
"""Main Page View"""
def get(self):
user = users.get_current_user()
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"
template_values = {
"url": url,
"url_linktext": url_linktext,
}
path = os.path.join(os.path.dirname(__file__), "index.html")
self.response.out.write(template.render(path, template_values))
class Recent(webapp.RequestHandler):
"""Query Last 10 Requests"""
def get(self):
#collection
collection = []
#grab last 10 records from datastore
query = ChangeModel.all().order("-date")
records = query.fetch(limit=10)
#formats decimal correctly
for change in records:
collection.append(decimal.Decimal(change.input)/100)
template_values = {
"inputs": collection,
"records": records,
}
path = os.path.join(os.path.dirname(__file__), "query.html")
self.response.out.write(template.render(path,template_values))
class Result(webapp.RequestHandler):
"""Returns Page with Results"""
def __init__(self):
self.coins = [1,5,10,25]
self.coin_lookup = {25: "quarters", 10: "dimes", 5: "nickels", 1: "pennies"}
def get(self):
#Just grab the latest post
collection = {}
#select the latest input from the datastore
change = db.GqlQuery("SELECT * FROM ChangeModel ORDER BY date DESC LIMIT 1")
for c in change:
change_input = c.input
#coin change logic
coin = self.coins.pop()
num, rem = divmod(change_input, coin)
if num:
collection[self.coin_lookup[coin]] = num
while rem > 0:
coin = self.coins.pop()
num, rem = divmod(rem, coin)
if num:
collection[self.coin_lookup[coin]] = num
template_values = {
"collection": collection,
"input": decimal.Decimal(change_input)/100,
}
#render template
path = os.path.join(os.path.dirname(__file__), "result.html")
self.response.out.write(template.render(path, template_values))
class Change(webapp.RequestHandler):
def post(self):
"""Printing Method For Recursive Results and While Results"""
model = ChangeModel()
try:
change_input = decimal.Decimal(self.request.get("content"))
model.input = int(change_input*100)
model.put()
self.redirect("/result")
except decimal.InvalidOperation:
path = os.path.join(os.path.dirname(__file__), "submit_error.html")
self.response.out.write(template.render(path,None))
def main():
application = webapp.WSGIApplication([("/", MainPage),
("/submit_form", Change),
("/result", Result),
("/recent", Recent)],
debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == "__main__":
main()
실용적인 면을 강조하는 튜토리얼답게, 우선 http://greedycoin.appspot.com이나 로컬에서 돌아가는 http://localhost:8080/를 살펴보는 것으로 시작해보자. 호박 색으로 뒤덮인 두 개의 플로팅(floating) 박스가 있는데, 왼쪽은 교환하고자 하는 돈의 액수를 넣는 곳이고, 오른쪽은 메뉴 박스이다. 화려할 수도 이상하게도 보일 수 있는 색과 레이아웃은 장고 템플릿과 CSS를 단순히 조합하여 만들어졌다. 장고 템플릿은 메인 디렉토리에, CSS 파일은 스타일시트에 위치해있다. 장고 템플릿은 GAE와는 상관이 없기 때문에, 이에 대해 잘 알지 못한다면 참고자료에 있는 장고 템플릿 링크를 따라가보기 바란다.
class MainPage(webapp.RequestHandler):
"""Main Page View"""
def get(self):
user = users.get_current_user()
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"
template_values = {
"url": url,
"url_linktext": url_linktext,
}
path = os.path.join(os.path.dirname(__file__), "index.html")
self.response.out.write(template.render(path, template_values))
Mainpage 클래스는 webapp.RequestHandler를 상속받았으며, get 메소드를 정의하면 사용자의 로그인 여부를 판단할 수 있는 페이지를 만들 수가 있다. 인증 부분 아래를 보면 알겠지만, 템플릿 시스템으로 넘어간 사용자 정보는 장고 템플릿을 통해 index.html로 렌더링된다. 한 가지 놀라운 사실은 페이지 인증을 거치기 위해 구글 유저 계정 데이터베이스를 이용한다 것이 너무나도 쉽다는 점이다. 바로 다음과 같이 말이다.
user = users.get_current_user()
if users.get_current_user():
이 코드로 이것저것 시도해보면서 인증된 사용자에게만 적용될 수 있는 코드를 추가해보도록 하자. 지금 당장 코드가 어떻게 돌아가는지 이해할 필요는 없고, 기존의 조건문을 활용해서 추가작업을 해보자.
댓글