この前作ったサンプルのデザインだけ流用して1時間以内でお小遣い帳にしてみた

仕様は、
・持ち金をチャージできる。
・チャージ時の総額と総利用額と残金を表示。
・使った時は、何に使ったかと金額を入力。
・過去20件の利用データを表示。
・過去100件の利用データ中の何に使ったかをドロップダウン表示して選択できる。
・エラーチェックはまだしていない。
・オモローと表示していた部分を「ご利用は計画的に。」に変更。


気づいたこと。知ったこと。


djangoのテンプレートに渡す値にmodelを使えるのが管理が煩雑にならないので楽だと思った。
・GQLでSQLのTOP 20をやりたいときは、ORDER BY等の後にLIMIT 20とやる。
・ORDER BY等はおおむねSQLと同じ。
・時間制限のため、コードが汚い(エクスキューズです。)。
・datetime型を使う場合はdatetimeモジュールをインポートする。
djangoのテンプレート側で四則演算が出来ない。
・スペルミスで結構エラーになった。

サンプルか修正したオブジェクトだけ表示。

・テンプレート

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="ja" xml:lang="ja" xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title>{{ userName }}のお小遣い帳</title>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<meta http-equiv="Content-Style-Type" content="text/css" />
		<meta http-equiv="Content-Script-Type" content="text/javascript" />
		<link href="./styles/styles.css" type="text/css" rel="stylesheet" />
  		<script type="text/javascript" src="./scripts/util.js" ></script>
  		<script type="text/javascript" src="./scripts/index.js" ></script>
	</head>
	<body>
	<div id="body">


		<div id="header">
			<div id="user">
			お小遣い帳
			</div>
				<div id="navigationOperation" >■</div>
		</div>
		

		<div id="navigation" >
			<div id="logonControl">
			{{ userName }} <br />
			<a href="{{ logoutUrl }}">ログオフ</a>
			</div>
			<div id="settings">
			<form action="/" method="post">
		        <div>年間チャージ額:<br /><input type="text" name="chargedValue" value="{{ setting.chargedValue }}" tabindex="1" accesskey="1" /><br /></div>
		        <div>前回チャージ後総額:<br />{{ setting.properValue }}円<br /></div>
		        <div>総利用額:<br />{{ setting.totalPayment }}円<br /></div>
		        <div>残額:<br />{{ currentValue }}円<br /></div>
		        <div><input type="submit" value="設定"  tabindex="2" accesskey="s" /></div>
		        {% if settingErrorMessage %}
		        <div class="errorMessage">{{ settingErrorMessage }} </div>
		        {% endif %}
	        </form>
			</div>
	        

		</div>
		<div id="contents">
			<form action="/" method="post">
		        <div>使った内容:<select name="titles" tabindex="3"> 
				<option value="" selected="selected"></option>
				{% for value in titles %}
				<option value="{{ value }}" >{{ value }}</option>
				{% endfor %}
				</select><input type="text" name="title" value="" tabindex="4" accesskey="c" /></div>
		        <div>使った金額:<input type="text" name="payment" value="" tabindex="5" accesskey="3" /><br /></div>
		        <div><input type="submit" value="設定"  tabindex="6" accesskey="s" /></div>
		        {% if paymentErrorMessage %}
		        <div class="errorMessage">{{ paymentErrorMessage }} </div>
		        {% endif %}
	        </form>
					
			<div id="list" >
			過去20件の利用状況:
			<table border="1" cellspacing="0" >
				<tr>
					<th>日付</th>
					<th>使った内容</th>
					<th>金額</th>
				</tr>
			{% for value in outputValues  %}
				<tr>
					<td>{{ value.date }}</td>
					<td>{{ value.title }}</td>
					<td>{{ value.value }}</td>
				</tr>
			{% endfor %}
			</table>
			</div>
		</div>

      <div id="footer">ご利用は計画的に。</div>
	</div>
	</body>
</html>	


・データモデル

# -*- coding: utf-8 -*-
from google.appengine.ext import db

class UserMaster(db.Model):
    #paymentを利用するユーザのマスタを定義するクラスです。
    #db.Modelを継承しています。
  author = db.UserProperty()
  chargedValue = db.IntegerProperty()
  totalPayment = db.IntegerProperty()
  properValue = db.IntegerProperty()
  
class PaymentInfo(db.Model):
  author = db.UserProperty()
  title = db.StringProperty()
  value = db.IntegerProperty()
  date = db.DateTimeProperty(auto_now_add=True)

・index.py

# -*- coding: utf-8 -*-
import wsgiref.handlers
import cgi
import datetime
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.api import users
import models
import os
from google.appengine.ext.webapp import template

from google.appengine.ext.db import djangoforms


class MainPage(webapp.RequestHandler):

    def view(self,user,settingErrorMessage = None,paymentErrorMessage = None):
      settings = models.UserMaster.gql("where author = :author",author=user)

      
      setting = None
      if settings.count() > 0:
        setting = settings[0]
      else:
        setting = models.UserMaster()
        setting.author = user
        setting.chargedValue = 600000
        setting.properValue = setting.chargedValue
        setting.totalPayment = 0
        setting.put()

      outputValues = models.PaymentInfo.gql("where author = :author order by date DESC LIMIT 20",author=user)

      titles = self.titles(user)
      template_values = {
        'userName' : user.nickname(),
        'logoutUrl': cgi.escape(users.create_logout_url("/")),
        'setting' : setting,
        'currentValue':setting.properValue - setting.totalPayment,
        'outputValues': outputValues,
        'titles': titles,
        'settingErrorMessage': settingErrorMessage,
        'paymentErrorMessage': paymentErrorMessage
        }

      path = os.path.join(os.path.dirname(__file__), 'index.html')
      self.response.out.write(template.render(path, template_values))
    
    def titles(self,user):
      selections = models.PaymentInfo.gql("where author = :author order by title",author=user)

      values = []
      prev = ''
      for value in selections:
        if prev != value.title:
          values.append(value.title)
          prev = value.title

      return values

    def get(self):
      user = users.get_current_user()

      if not user:
        self.redirect(users.create_login_url(self.request.uri))
        return        
      self.view(user)

    def post(self):
      user = users.get_current_user()
      if not user:
          self.redirect(users.create_login_url(self.request.uri))
          return

      if self.request.get('chargedValue'):
        if self.request.get('chargedValue').isdigit():
          settings = models.UserMaster.gql("where author = :author",author=user)
          setting = settings[0]
          setting.properValue = setting.properValue + int(self.request.get('chargedValue'))
          setting.put()
        else:
          self.view(user,u'チャージ金額には数字を入力してください。')
          return
      else:
        payment = models.PaymentInfo()
        payment.author = user
        if len(self.request.get('titles')) == 0:
          payment.title = self.request.get('title')
        else:
          payment.title = self.request.get('titles')
        payment.value = int(self.request.get('payment'))
        payment.put()
        settings = models.UserMaster.gql("where author = :author",author=user)
        setting = settings[0]
        setting.totalPayment = setting.totalPayment + payment.value
        setting.put()

      self.view(user)

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


if __name__ == '__main__':
    main()