GoogleSpreadSheet のWeb公開の方法

任意のWebページに埋め込みで公開したい場合の画面操作メモです。

ブラウザでGoogleアカウントに入って公開したいGoogleSpreadSheet を開きます
f:id:posturan:20210801122129j:plain

ファイルメニューから「ウェブに公開」を選択
f:id:posturan:20210801122237j:plain

「埋め込み」を選択して公開するコンテンツを、ドキュメント全体ではなく、
シートを選択
f:id:posturan:20210801123701j:plain

公開をクリックすると確認がある
f:id:posturan:20210801123818j:plain

確認すると、埋め込み用の iframe HTMLタグが出るのでこれをコピーして使用する
f:id:posturan:20210801123933j:plain

公開を停止していると、以下のように iframe の部分は、公開されていないメッセージ表示になる。
f:id:posturan:20210801124043j:plain

Handsontable CSV出力

無償版の Handsontable Ver6.2.2 を使ったとき、HandsontableからCSV出力
を簡単にできるものを探していた。

https://github.com/juantascon/jquery-handsontable-csv

を見つけた、MITライセンスである。
中身をよく見ると

var csv = "sep=;\n"
csv += headers.join(";") + "\n";
csv += row.join(";")

と書かれていて区切り文字がカンマではく、";" セミコロンになっているしかも、sep=; と先頭行をつけている。
これでは、カンマ区切りCSVとして意図したものでななくなってしまう。
だから、以下のとおり修正して使えば良いであろう。

var handsontable2csv = {
    string: function(instance) {
        var headers = instance.getColHeader();
        var csv = "";
        for (var i = 0; i < instance.countRows(); i++) {
            var row = [];
            for (var h in headers) {
                var prop = instance.colToProp(h)
                var value = instance.getDataAtRowProp(i, prop)
                row.push(value)
            }
            csv += row.join(",")
            csv += "\n";
        }
        return csv;
    },
    download: function(instance, filename) {
        var csv = handsontable2csv.string(instance)
        var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
        var link = document.createElement("a");
        link.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(csv));
        link.setAttribute("download", filename);
        document.body.appendChild(link)
        link.click();
        document.body.removeChild(link)
    }
}

ページ数、構成が大きい Flask Blueprint 使用方法

共通で使用するCSS、JS が存在しページ毎の CSS 、JS を構成しなければならず
複数ページを大量に構築する場合の、Flask Blueprintを使用する方法

注意すべきは、
・Flask で指定したテンプレートフォルダに、Blueprint でテンプレート走査するフォルダを
 追加はできるが、実行する Blueprint で1つに限定はできないことである。
 → 1つに限定されてしまうと、共通のレイアウトHTML 、各個別のレイアウトHTMLを同じ
  名称にすると、ぶつかってしまう。

これ以外は以下サンプルが示すように、共通のCSS, JS ページ毎の CSS 、JS を配置
をすることができる。
サンプルは、共通 common の レイアウト、CSS、JS に対して、
page1、page2、。。。と増えていくサンプルである。
f:id:posturan:20210728234538j:plain
page1 の views.py

# -*- coding: utf-8 -*-
#  page1/views.py
from flask import Blueprint, render_template

# page1のBlueprint
page1 = Blueprint('page1', __name__, url_prefix='/page1',
                  template_folder='templates',
                  static_url_path='/static', static_folder='./static')

@page1.route('/')
def page1_a():
    info = 'Blueprint テスト'
    return render_template("index1.html", title='page1 タイトル', info=info)

page2 の views.py も同様に作成する
 template_folder は、import os をして
  template_folder=os.path.join(os.path.dirname(__file__), 'templates')
 と書いても同じである。

Webを起動する app.py

# -*- coding: utf-8 -*-
#  app.py
import os
from flask import Flask
from page1.views import page1
from page2.views import page2

tempfolder = os.path.join(os.path.dirname(__file__), 'common', 'layout')
app = Flask(__name__, template_folder=tempfolder, static_folder='common')
app.register_blueprint(page1)
app.register_blueprint(page2)

if __name__ == '__main__':
    app.run(host='localhost', port=80, debug=True)

共通の static フォルダ、common から 共通テンプレートを置いた layout フォルダを指定し
page1 、page2 を生成して Blueprint ととして登録している。
この時、page1 、page2で指定したテンプレートフォルダが走査対象として登録されるのであり、
page1 の下の templates 配下の HTMLファイル名称と
page2 の下の templates 配下の HTMLファイル名称を同じにするとぶつかってしまう。

layout.html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<link href="{{url_for('static', filename='css/common.css')}}" rel="stylesheet" type="text/css"/>
<title>{{title}}</title>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://momentjs.com/downloads/moment-with-locales.js"></script>
<script type="text/javascript" src="{{url_for('static', filename='js/jholiday.js')}}"></script>
{% block head %}
{% endblock %}
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>

url_for() で、'static' を参照、filename が指す CSS or JS を読み込むように指定している。
{% block head %} で、ページ側で、HTMLヘッダで追加するもの
{% block content %} で、HTML body を書かせるようにしている

index1.html

{% extends "layout.html" %}
{% block head %}
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link href="{{url_for('static', filename='css/ui_datepicker_holiday.css')}}" rel="stylesheet" type="text/css"/>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link href="static/css/page1.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="static/js/page1.js"></script>
{% endblock %}
{% block content %}
<h2>Hello</h2>
Hello Page : {{info}}
<form>
<table>
	<tr>
		<td>Date</td><td><input id="datepicker" type="text" name="date" readonly="readonly"></td>
		<td><button id="check" type="button">check</button></td>
		<td id="week"></td><td id="desc"></td>
	</tr>
</table>
</form>
   :::::::::::::::
   省略
   :::::::::::::::
{% endblock %}

個別ページのHTMLで共通に配置した CSS、JS を読み込む場合は、
url_for() で 'static' をキーに filename で指定する

Flask デフォルトの参照フォルダを変更する

Flask インスタンスを run 実行するスクリプトと同じ階層にあるフォルダ名
 templates ・・・HTMLを置くフォルダ
 static ・・・CSS, JSを置くフォルダ
デフォルトの構成
/root
|
+--- static
|   |
|   +--- common.css
|   +--- common.js
|
+--- templates
|   |
|    +--- index.html
|    +--- layout.html
|
+---- run.py

index.html

{% extends "layout.html" %}
{% block content %}
Message : {{message}}
{% endblock %}

layout.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>

run.py

from flask import Flask, render_template
@app.route('/')
def home):
    msg = 'メッセージ'
    return render_template("hello.html", title='Home',  message=msg)
if __name__ == '__main__':
    app.run(port=80, debug=True)

がデフォルトであるが、
これを変える方法、
template_folder 、static_folder を指定して変更する

app = Flask(__name__, template_folder='templates', static_folder='static')

PyCharm の起動画面

PyCharm の起動後の画面、プロジェクトを毎回選択させる画面にするには、
f:id:posturan:20210726221701j:plain
設定で、「起動時に前回のプロジェクトを開く」のチェックをはずす。
デフォルトは、チェックONになっている。
そうすれば、以下のように起動後はプロジェクト選択の画面になる
f:id:posturan:20210726222009j:plain

Python で telnet メモ

標準ライブラリ telnetlib
telnetlib --- Telnet クライアント — Python 3.9.4 ドキュメント

https://runebook.dev/ja/docs/python/library/telnetlib


PythonのtelnetlibでNW機器(Cisco)にリモートログイン - Qiita


stackoverflow.com

telnetlibのTelnetでコマンド実行結果だけを取得する。 - oxdbのブログ

Jackson LocalTimeDeserializer の注意

Jackson で、JSR-310 対応の LocalTime をデシリアライズする設定で
なぜか、次の方法で JavaTimeModule を設定しようすると、
 メソッド addDeSerializer(Class, LocalTimeDeserializer) は型 SimpleModule で未定義です
コンパイルエラーになる。

JavaTimeModule jtm = new JavaTimeModule();
jtm.addDeSerializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)

ObjectMapper mapper = new ObjectMapper().registerModule(jtm);

LocalTimeDeserializer.INSTANCE を指定するのだから、デフォルトのフォーマット ISO_LOCAL_TIME を適用するはずなのだが。。

以下に書き直せば、コンパイルエラーにならない。

JavaTimeModule jtm = new JavaTimeModule();
jtm.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ISO_LOCAL_TIME))

ObjectMapper mapper = new ObjectMapper().registerModule(jtm);