Google App Engineでone-to-one(1対1)Djangoフォームで
2010/04/28 18:36:33
「Google App Engineでone-to-one(1対1)」で作成した複数モデル連携をDjangoフォームを導入したバージョンも作ってみる。連携しているモデルを自動で引っ張ってきてくれてドロップダウンメニューを作ってくれるからこれまたかなり便利だが、フォームを生成している中身はまったくカスタマイズできない。
そういったかゆいところに手が届かない感じもあるが、例によって複数モデルでもバリデーションをしっかりやってくれるし、コードも短くなるので使ってもいいケースもあるかも。
全く変更ないテンプレートは省略してます。
app.yaml
main.py
template/author/add.html
template/author/edit.html
template/book/add.html
template/book/edit.html
う〜ん、便利といえば便利なのだが…
app.yaml
application: jinling-ren version: 1 runtime: python api_version: 1 handlers: - url: .* script: main.py
main.py
#!/usr/bin/env python
#!-*- coding:utf-8 -*-
# one-to-one(Django)サンプル
# http://www.jinlingren.com/
from google.appengine.ext import webapp, db
from google.appengine.ext.webapp import util, template
from google.appengine.ext.db import djangoforms
import os
import cgi
import logging
class Author(db.Model):
name = db.StringProperty(required=True, verbose_name='著者')
modified = db.DateTimeProperty(auto_now=True)
created = db.DateTimeProperty(auto_now_add=True)
def __unicode__(self):
return self.name
class Book(db.Model):
title = db.StringProperty(required=True, verbose_name='タイトル')
author = db.ReferenceProperty(reference_class=Author, verbose_name='著者')
modified = db.DateTimeProperty(auto_now=True)
created = db.DateTimeProperty(auto_now_add=True)
class AuthorForm(djangoforms.ModelForm):
class Meta:
model = Author
exclude = {}
class BookForm(djangoforms.ModelForm):
class Meta:
model = Book
exclude = {}
class Root(webapp.RequestHandler):
def get(self):
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'index.html'),
{}
)
self.response.out.write(html)
class AuthorList(webapp.RequestHandler):
def get(self):
authors = Author.all().order('-created')
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'author', 'list.html'),
{
'authors': authors
}
)
self.response.out.write(html)
class AuthorView(webapp.RequestHandler):
def get(self, key):
author = db.get(db.Key(key))
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'author', 'view.html'),
{
'author': author
}
)
self.response.out.write(html)
class AuthorAdd(webapp.RequestHandler):
def get(self):
authorform = AuthorForm()
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'author', 'add.html'),
{
'authorform': authorform
}
)
self.response.out.write(html)
def post(self):
try:
authorform = AuthorForm(data=self.request.POST)
if authorform.is_valid():
authorform.save()
self.redirect('/author/list')
else:
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'author', 'add.html'),
{
'authorform': authorform
}
)
self.response.out.write(html)
except:
self.redirect('/author/add')
class AuthorEdit(webapp.RequestHandler):
def get(self, key):
author = db.get(db.Key(key))
authorform = AuthorForm(instance=author)
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'author', 'edit.html'),
{
'key': key,
'authorform': authorform
}
)
self.response.out.write(html)
def post(self, key):
try:
author = db.get(db.Key(key))
authorform = AuthorForm(data=self.request.POST, instance=author)
if authorform.is_valid():
authorform.save()
self.redirect('/author/list')
else:
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'author', 'edit.html'),
{
'key': key,
'authorform': authorform
}
)
self.response.out.write(html)
except:
self.redirect('/author/edit/'+key)
class AuthorDelete(webapp.RequestHandler):
def get(self, key):
try:
author = db.get(db.Key(key))
if author:
books = author.book_set
if books is not None:
for book in books:
book.author = None
book.put()
author.delete()
self.redirect('/author/list')
except:
self.redirect('/author/list')
class BookList(webapp.RequestHandler):
def get(self):
books = Book.all().order('-created')
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'book', 'list.html'),
{
'books': books
}
)
self.response.out.write(html)
class BookView(webapp.RequestHandler):
def get(self, key):
book = db.get(db.Key(key))
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'book', 'view.html'),
{
'book': book
}
)
self.response.out.write(html)
class BookAdd(webapp.RequestHandler):
def get(self):
bookform = BookForm()
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'book', 'add.html'),
{
'bookform': bookform
}
)
self.response.out.write(html)
def post(self):
try:
bookform = BookForm(data=self.request.POST)
if bookform.is_valid():
bookform.save()
self.redirect('/book/list')
else:
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'book', 'add.html'),
{
'bookform': bookform
}
)
self.response.out.write(html)
except:
self.redirect('/book/add')
class BookEdit(webapp.RequestHandler):
def get(self, key):
book = db.get(db.Key(key))
bookform = BookForm(instance=book)
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'book', 'edit.html'),
{
'key': key,
'bookform': bookform
}
)
self.response.out.write(html)
def post(self, key):
try:
book = db.get(db.Key(key))
bookform = BookForm(data=self.request.POST, instance=book)
if bookform.is_valid():
bookform.save()
self.redirect('/book/list')
else:
html = template.render(
os.path.join(os.path.dirname(__file__), 'template', 'book', 'edit.html'),
{
'key': key,
'bookform': bookform
}
)
self.response.out.write(html)
except:
self.redirect('/book/edit/'+key)
class BookDelete(webapp.RequestHandler):
def get(self, key):
try:
book = db.get(db.Key(key))
if book:
book.delete()
self.redirect('/book/list')
except:
self.redirect('/book/list')
def main():
application = webapp.WSGIApplication(
[
('/', Root),
('/author/list', AuthorList),
('/author/view/(\w+)', AuthorView),
('/author/add', AuthorAdd),
('/author/edit/(\w+)', AuthorEdit),
('/author/delete/(\w+)', AuthorDelete),
('/book/list', BookList),
('/book/view/(\w+)', BookView),
('/book/add', BookAdd),
('/book/edit/(\w+)', BookEdit),
('/book/delete/(\w+)', BookDelete)
],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
template/author/add.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>one-to-one(Django)サンプル</title>
</head>
<body>
> <a href="/book/list">著書一覧</a><br><br>
<h1>AuthorAdd(著者追加)</h1>
> <a href="/author/list">著者一覧</a><br><br>
<form action="/author/add" method="post">
<table cellspacing="1" cellpadding="8" border="1">
{{ authorform }}
</table><br>
<input type="submit" value="追加する">
</form>
<br>
<font color="#FF0000">*</font>は必須項目
</body>
</html>template/author/edit.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>one-to-one(Django)サンプル</title>
</head>
<body>
> <a href="/book/list">著書一覧</a><br><br>
<h1>AuthorEdit(著者編集)</h1>
> <a href="/author/list">著者一覧</a><br><br>
<form action="/author/edit/{{ key }}" method="post">
<table cellspacing="1" cellpadding="8" border="1">
{{ authorform }}
</table><br>
<input type="submit" value="変更する">
</form>
<br>
<font color="#FF0000">*</font>は必須項目
</body>
</html>template/book/add.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>one-to-one(Django)サンプル</title>
</head>
<body>
> <a href="/author/list">著者一覧</a><br><br>
<h1>BookAdd(著書追加)</h1>
> <a href="/book/list">著書一覧</a><br><br>
<form action="/book/add" method="post">
<table cellspacing="1" cellpadding="8" border="1">
{{ bookform }}
</table><br>
<input type="submit" value="追加する">
</form>
<br>
<font color="#FF0000">*</font>は必須項目
</body>
</html>template/book/edit.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>one-to-one(Django)サンプル</title>
</head>
<body>
> <a href="/author/list">著者一覧</a><br><br>
<h1>BookEdit(著書編集)</h1>
> <a href="/book/list">著書一覧</a><br><br>
<form action="/book/edit/{{ key }}" method="post">
<table cellspacing="1" cellpadding="8" border="1">
{{ bookform }}
</table><br>
<input type="submit" value="変更する">
</form>
<br>
<font color="#FF0000">*</font>は必須項目
</body>
</html>う〜ん、便利といえば便利なのだが…