HOME > ブログ > Google App Engineでone-to-one(1対1)Djangoフォームで

Google App Engineでone-to-one(1対1)Djangoフォームで

Google App Engineでone-to-one(1対1)」で作成した複数モデル連携をDjangoフォームを導入したバージョンも作ってみる。
連携しているモデルを自動で引っ張ってきてくれてドロップダウンメニューを作ってくれるからこれまたかなり便利だが、フォームを生成している中身はまったくカスタマイズできない。
そういったかゆいところに手が届かない感じもあるが、例によって複数モデルでもバリデーションをしっかりやってくれるし、コードも短くなるので使ってもいいケースもあるかも。


全く変更ないテンプレートは省略してます。

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>



う〜ん、便利といえば便利なのだが…
| Google App Engine | Comment:0 |
コメント投稿












画像リロード
*半角の小英字、数字で構成されています