LoginSignup
1

More than 3 years have passed since last update.

python Bottleの基本9 Form

Posted at

このテーマは、入力フォームをサクッと作るです。特に日本語入力があるフォームは、文字化けしたりフォームが崩れたり、すべったり転んだりします。そこでテンプレートを作っておきます。

image.png

ex9.py
from bottle import *
import json,os
#HTML デコレーション(Bootstrap4)
def Html(title):
    html='''
        <!DOCTYPE html>
            <html lang="ja">
            <head>
                <meta charset="utf-8" />
                <title>%s</title>
                <link rel="stylesheet" type="text/css" href="/static/content/bootstrap.min.css" />
                <link href="static/content/jumbotron.css" rel="stylesheet" />
                <link rel="stylesheet" type="text/css" href="/static/content/site.css" />
                <script src="/static/scripts/modernizr-2.6.2.js"></script>
                <script src="/static/scripts/jquery-1.10.2.min.js"></script>
                <script src="/static/scripts/bootstrap.min.js"></script>
                <script src="/static/scripts/respond.min.js"></script>
                <script src="/static/scripts/mindmup-editabletable.js"></script>
            </head>
            <body>
            %s          
            </body>
            </html>'''
    def f0(f):
        def f1(*a,**b):          
            return html%(title,f(*a,**b))
        return f1
    return f0
def Body():
    def f0(f):
        def f1(*a,**b):
            return '<div class="container body-content">%s</div>'%f(*a,**b)
        return f1
    return f0
def Navi(menu):
    nav='''<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
            <a class="navbar-brand" href="/">%s</a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarsExampleDefault">
            <ul class="navbar-nav mr-auto">
                %s
            </ul>
            <form class="form-inline my-2 my-lg-0">
                <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
                <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
            </form>
            </div>
     </nav>%s'''
    def f0(f):
        def f1(*a,**b):
            nm=''.join(['<li class="nav-item"><a class="nav-link" href="/%s">%s</a></li>'%(x,x) for x in menu[1:]])
            return nav%(menu[0],nm,f(*a,**b))
        return f1
    return f0
def routes(menu):
    def f0(f):
        route('/','GET',f)
        [route("/%s"%x,'GET',f) for x in menu]
        def f1(*a,**b):
            return f(*a,**b)
        return f1
    return f0
#JOMBOTRON デコレーション
def Jumbotron(title,paragraph):
    jumbo='''<div class="jumbotron">
        <div class="container">
          <h1 class="display-3">%s</h1>
          <p>%s</p>
        </div>
      </div>%s'''
    def f0(f):
        def f1(*a,**b):
            return jumbo%(title,paragraph,f(*a,**b))
        return f1
    return f0

def form(nm):   
    x0='''<div class="container" style="margin-top:2em;">
    <form class="form" role="form" action="/form" method="post">
        %s
        <button type="submit" class="btn btn-primary ">登録</button>
    </form>
</div>'''
    x1='<div class="form-group row">%s</div>'
    x2='''<label for="{0}" class="col-sm-4 control-label">{0}</label>
    <div class="col-sm-8">
        <input name="{0}" type="text" id="{0}" placeholder="{0}" class="form-control" autofocus>
    </div>'''
    ax=''.join([''.join([x1%x2.format(a) for a in x.split(' ')])for x in nm])
    return x0%ax
menu='Home,Form,Menu2,Menu3,Disp'.split(',')
@routes(menu)
@Html('Hello')
@Navi(menu)
@Jumbotron('Formテンプレート','これさえあればサクッと作ることができます')
@Body()
def Home():
    p=request.urlparts[2]
    if p=='/Form':
        return form("名前,電話番号,メール,郵便番号,住所".split(','))
    return "<h1>%s</h1><h1>Hello World</h1>"%(p)
def vTable(d):
        b="\n".join(["<tr><th>%s</th><td>%s</td></tr>"%(x,d[x])for x in d])
        h=["<table style='margin-top:3em;' class='table table-sm table-bordered table-striped table-responsive-sm table-hover'>",
           b,"</table>"]
        return "\n".join(h)+"<button class='btn btn-primary' onclick='history.back()'>戻る</button>"

@route('/form',method="POST")
@Html('Hello')
@Jumbotron('Form表示テンプレート','これさえあればサクッと作ることができます')
@Navi(menu)
@Body()
def form_post():
    tbl={x: request.params.decode()[x] for x in request.params.decode()}
    htm=vTable(tbl)
    return htm
#メニューの設定
#faviconの読み込み    
@route('/favicon.ico')
def favcon():
    return static_file('favicon.ico', root='./static')
#staic ファイルの読み込み
@route('/static/<filepath:path>')
def server_static(filepath):
    return static_file(filepath, root='./static')
#web server のhost portの設定
HOST,PORT='localhost',8080
if __name__ =='__main__':
    run(host=HOST,port=PORT)

スニペット解説

return form("名前,電話番号,メール,郵便番号,住所".split(','))

formのHtmlを生成しています。カンマ区切りの項目を変えれば自由にカスタマイズできます。

def form_post():
    tbl={x: request.params.decode()[x] for x in request.params.decode()}
    htm=vTable(tbl)
    return htm

POSTされたデータをUTF-8にでコードしてdictを作っています。
vTableは、垂直方向に見出しするテーブルのhtmlを生成しています。
image.png

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1