DjangoCongress JP 2018で発表するまでの準備を振り返ってみた #djangocongress

前回書いた通り、DjangoCongress JP 2018にて発表しました。
DjangoCongress JP 2018

ただ、カンファレンスでの発表は未経験だったので、ゼロから準備をしました。

今書かないと忘れてしまいそうなので、発表するまでの準備を振り返ってみます。

 
なお、CfPを出した時点の、自分のスペックは以下の通りです。

  • Blog書いているので、文章を書くのは苦にならない
  • 話すのは苦手
  • 勉強会でのLTは経験あるが、毎回やっても緊張が解けない
  • 45分のトークは未経験

 
目次

 

長いのでまとめ

  • CfP・スライド・動画が公開されているPyCon JPの情報はありがたい
    • 2012年〜2017年まである
  • 発表資料作成は、Marpさまさま

 

CfP出すまで

社内のCfPネタ出しにて、sin_tanaka からMiddlewareネタでいけると言われました。

(ヾノ・∀・`)

と思ったのですが、ネタをもらったのに何もしないのは良くないと考え、CfPを提出することにしました。

 
とはいえ、CfPを書いたことがないのでフォーマットを探しました。

PyCon JPのサイトを見ると、プロポーザルリストがありました。
https://pycon.jp/2017/ja/proposals/vote_list/

 
そこで、PyCon JPのプロポーザルに従って、以下のプロポーザルを3/5に出しました。締切直前...

対象レベル:
初級


説明:
Djangoでアプリケーションを作る際、全部のリクエスト/レスポンスをフックし、何か処理を行いたいことがあります。

例えば、全画面でログイン必須にするとします。この場合、全部のViewに対してデコレータ・Mixinを追加しても良さそうです。

しかし、その場合、同じような処理を複数箇所に書くことになります。その結果、新規作成やメンテナンス時の作業漏れにより、不具合が発生する可能性があります。

そうならないための仕組みとして、DjangoにはDjangoミドルウェアという仕組みがあります。これを使うことで、リクエスト/レスポンスをフックして、自分の処理を追加できます。

また、DjangoはWSGIに沿ったフレームワークのため、WSGIミドルウェアを使用してもリクエスト/レスポンスをフックできます。

そこでこのセッションではDjangoにDjango/WSGIミドルウェアを組込む例を示しながら

・なぜDjango/WSGIミドルウェアを使うのか
・Djangoミドルウェアとは
・WSGIミドルウェアとは
・WSGIとは
・ミドルウェアを複数組み込んだ時の動作順
・ミドルウェアでの例外ハンドリング
・Djangoミドルウェア/WSGIミドルウェアの実例

などをご紹介します。


話せないこと:
・凄いDjango/WSGIミドルウェアを作って公開した経験や話


備考:
以前ブログに書いた内容を元に、最近のDjangoに追随した内容を予定しています。
http://thinkami.hatenablog.com/entry/2016/12/13/061856

 
その4日後、

thinkAmi さんの「Django/WSGIミドルウェアについて」は選考の結果、採用となりました。

の連絡をいただきました。驚きました。

 

タスク洗い出しとスケジュール化

ボーっと過ごしているとあっという間に本番を迎えそうだったため、タスクの洗い出しとスケジュール化を行いました。

弊社内のGitLabにリポジトリを作り、Boardを使ってタスク化しました。

今振り返ると、スケジュールを破ったものが多いですが、タスクの洗い出しができていたため、そこまで焦ることはありませんでした。

 

発表方法の調査

カンファレンスでの発表方法について、そもそもよく分かっていないことに気づきました。

そこで、PyCon JPのサイトを見たところ、過去の動画が公開されていました。
https://pycon.jp/2017/ja/schedule/

そのため、それらの動画を視聴し、流れや雰囲気などを確認しました。

 
また、合わせて近隣の図書館に出かけ、タイトルに プレゼン発表 と名前が付いている書籍を読みました。

乱読するうちに、発表は

  • TEDっぽいの
  • 企業間のコンペっぽいの
  • 学会発表っぽいの

の3種類に分かれそうだと気づきました。

今回のDjangoCongress JPネタの場合、学会発表が一番近いだろうと感じました。

そのため、学会発表 と書かれているものについても読むことにし、最終的には20冊くらいになりました。

 
複数の書籍を読んだことで、どの書籍でも言われていることを中心すればハズレがなさそうとの実感を得ました。

当日も、「理系のための口頭発表術」をお守り代わりに持っていきました。

理系のための口頭発表術―聴衆を魅了する20の原則 (ブルーバックス)

理系のための口頭発表術―聴衆を魅了する20の原則 (ブルーバックス)

 

プレゼン小道具の検討

動画や書籍を見たり、軽くプレゼンの素振りをするうちに、プレゼン小道具がいるかもしれないと思い、検討してみました。

 

プレゼンター

動画を見るとプレゼンターを使っている方がいたため、どんな機能が必要か考えてみました。

 

スライド切替

スライド切替なしでもいけそうでした。

ただ、当日の緊張を考えると、スライドの進むボタンを押せばいいだけになるスライド切替器が欲しくなりました。

 

レーザーポインタ

スライドで説明している部分を指すのがあると良いかなと思いました。

ただ、当日の緊張を考えると、ポインタ位置がブレブレになり見づらくなるだろうと考えました。

そのため、今回レーザーポインタはやめておきました。

 

最終的に用意したもの

ロジクールR400t です。

ロジクール ワイヤレス プレゼンター R400t

ロジクール ワイヤレス プレゼンター R400t

大きめで握りやすいのと、スライドを進めるボタンが押しやすそうということで選びました。

サポートOSにはMacの文字はありませんでしたが、ドライバをインストールしなくてもそのまま使えました。

 
R400tにはレーザーポインタ機能がありますが、前述の通りレーザーポインタは使いません。

そこで、指し棒を使えば、スライドで説明している部分を指せると思いました。

ただ、片方の手にハンドマイク、もう片方にR400tを持つと、手が足りません。

都度持ち替えすることも考えましたが、当日の緊張を考えると、持ち替える時にそれらを落とす可能性が高そうでした。

 
仕方ないので、指し棒は使わず、

  • 位置を示す必要がないくらいまで、スライド中の情報量を減らす
  • 減った情報量は、スライドの枚数を増やすことで、全体の情報量は変更しない

とスライド構成でカバーすることにしました。

 

時間配分表

時間厳守するために、何らかの方法が必要でした。

そんな中、以下の記事を目にしました。
岡山で「ITエンジニアの生存戦略」について話してきました #oso2018 - give IT a try

この中の「60分ちょうどで発表を終わらせるコツ」にて、時間配分表について書かれていました。

まさにこれだと感じ、自分も用意しました。

 
とはいえ、前日のホテルで気づいたので、ホテルのWindowsとプリンターを借りて出力しました。

そのWindowsにはOffice系のソフトが無かったため、ワードパットを使ってフォントサイズを調整しつつ、何とか出力しました。

 
なお、失敗したのは、時間配分表の書き方でした。

時間が増える形式で書いたものの、会場のプレゼンタイマーは時間が減っていく形式でした。

そのため、発表しつつ残り時間を計算するハメになりました。

 

一般的なスライド量の把握

45分の場合、どれだけ枚数を用意すれば良いのか分かりませんでした。

そこで、PyCon JPのトーク時間とスライド量を調べてみました。

その結果、自分の説明能力であれば80枚前後を用意すれば何とかなるという目安が得られました。

 
とはいえ、実際に書いてみたところ、最終的には105枚になってしまいましたが...

 

スライドの作成

PowerPointのようなプレゼンソフトにいきなり書いていく場合、全体像が見えなくて苦しむだろうと考えました。

そのため、Blogを書くような感じで

  • 目次を作成
  • 目次に従い、Markdownで内容を追加

という順で作業を行いました。

 
また、スライドの形式で見れば気づくことも多そうと考え、Markdownをスライド化できるMarpを使いました。
Marp - Markdown Presentation Writer

元データがMarkdownだったので、資料のページを入れ替えるなども楽でした。

なお、スライドを書いている時点では、Marpを使った発表は考えていませんでした。現時点(v0.0.12)では、プレゼンテーションモードが搭載されていないためです(pdf書き出しは可能)。

 

発表の素振り

1週間くらい前に、ひと通りのスライドができあがったため、発表の素振りを始めました。

スマホの音声レコーダーを使いながら、スライドを読み上げました。

その際、詰まったところや説明しづらいと気づいたら、随時、音声レコーダーを一時停止しつつスライドの修正を行いました。

最初の頃、読み上げとスライドの修正を別の時間でやろうとしたら、スライドの修正箇所を忘れてしまったこともあり、これはやってみないと分からないと感じました。

 
とはいえ、最初は読み上げるのが手間であり、積極的にやろうという気にはなりませんでした。

ただ、素振りを繰り返していくうちに、話しやすいスライドに修正されていくことに気づき、これは良いとの実感を得ました。

そのため、時間をみて素振り & 資料修正するようになりました。

 
10回を超えた頃からだいたい内容が頭に入り、長さがバラバラだった発表時間も安定するようになりました。

素振りの回数は発表の得手不得手により変わってくるかと思いますが、自分はこれくらいやらないとダメでした。

 

あきらめた発表スタイル

素振りを繰り返すと、自分にできることとできないことが大体わかってきました。

あきらめたスタイルは次のようなものです。

 

スライドの量を減らして、口頭説明多くする

元々アドリブが弱いため、口頭説明を臨機応変にやると失敗すると感じました。

そのため、スライドに内容をある程度書いて、あとは読み上げていくスタイルにしました。

とはいえ、素振りして何となく覚えてしまったものは、スライドから削除していきました。

 

落ち着いた語り口

緊張すると早口になるため、落ち着いた語り口にしようと考えていました。

しかし、どうやっても緊張がとれません。

そのため、時間配分表を見て、あまりに早い場合には軌道修正しようと考えました。

 

ウケを狙う

日頃できないものは無理なので、あきらめました。

 

Marpについて

今回はMarpで書き出したpdfを使いました。その経緯や対応は以下です。

 

プレゼンツールの選択(Marp & pdf)

だいたいの内容が固まった3日前くらいに、PowerPointなどのプレゼンツールに移植しようと考えました。Marpにプレゼンテーションモードが無かったというのもあります。

ただ、何も設定していないPowerPointだったので、フォントの用意やマスタースライドの調整など、移植するまでに時間がかかりそうでした。

そのため、Marpでスライドをpdf化し、Adobe Readerのフルスクリーン表示で発表することにしました。

 

Marpのテーマ変更

MarpのGaiaテーマを使うことで、パッと見、いい感じのスライドになりました。

ただ、MarpのGaiaテーマで気になったのは、ソースコードの背景が黒だったことです。

黒背景はターミナルっぽくて良いのですが、過去の知見より、会場の光量によってはスライドが見づらくなると感じました。

そのため、以下の内容でテーマを変更しました。

  • 黒背景から、白背景へ
  • バックのグラデーションをとりやめ
  • 色数を減らすため、シンタックスハイライトを sunburst から github

 
なお、Marpでのスタイル変更は、以下の記事が参考になりました。ありがとうございました。

 
また、変更したテーマは、Marpをforkして、ブランチ theme/thinkami の中に入れてあります。
https://github.com/thinkAmi/marp

 

前日

書籍「理系のための口頭発表術」に、「発表練習は前日夜にはやらない」と書かれていたため、前日朝を最後に練習はやめました。

社内Slackが資格試験で盛り上がっていたので自分も参加してみたり、フラフラ散歩していました。

 

当日

当日は、緊張のために食欲もそんなにわかないだろうと思い、ベーグルとゼリー飲料を持ち込みました。

その時間になると、案の定、緊張してました。そのため、食欲がありませんでしたが、飲み込みやすいものだったためお腹にものを入れることができ、空腹を避けられました。

 
また、時間配分表のおかげで、前半遅れたのを把握できたので、後半調整できました。そのおかげで、1分くらい残して発表を終えました。ただ、質疑応答の時間が取れずに申し訳なかったです。

発表の結果については、前回の記事にも書きましたが、好意的な意見が多くてホッとしました。

 

まとめ

再掲となりますが。

  • CfP・スライド・動画が公開されているPyCon JPの情報はありがたい
    • 2012年〜2017年まである
  • 発表資料作成は、Marpさまさま

 
めったにない経験ができて、とても楽しかったです。ありがとうございました。

DjangoCongress JP 2018 に参加 & 発表しました #djangocongress

5/19に開催された、DjangoCongress JP 2018に参加 & 発表しました。
DjangoCongress JP 2018

場所は、サイボウズ株式会社の東京オフィスでした。
東京オフィス アクセスマップ | サイボウズ株式会社

 
会場の内装が凝っていたり、バーっぽいところがあったり、スカイツリーが見えたりと、素敵な会場でした。

 
自分の発表、および全体を通してのメモを残します。誤りがありましたらご指摘ください。

 
目次

自分の発表「Django/WSGIミドルウェア入門」

スライドです。

また、発表で使用したソースコードは、以下のリポジトリに公開してあります。
https://github.com/thinkAmi/DjangoCongress_JP_2018_talk

なお、プレゼンの対応バージョンは

です。

 
プレゼン資料は

を元に構成しました。

 
その結果、主な内容は

となりました。

 
なお、公式ドキュメントに記載が無いがプレゼン資料に記載したものは

  • process_view() の戻り値が render() メソッドを持つ場合は、 process_template_response() フックも動作する

の箇所です。

ソースコードを見ると

となっており、また動作も確認していますので、問題ないかと思います。

 
発表自体は緊張のあまり早口 & カミカミでしたが、聴いてくださっていた方々のツイートを見ると好意的なコメントをいただけていたようです。ありがたいばかりです。

 
また、発表直後に運営者の方々から

  • 初めてなのに発表が上手だった (@hirokikyさん)
  • スライドがシンプルにまとまっていてよかった (スタッフの方 *1 )

という旨のフィードバックをいただきました。最低限の仕事は果たせたのかなと感じるとともに、発表に不慣れな自分には今後の励みや指針となりました。ありがとうございました。

また、即座のフィードバックを通じて、DjangoCongressをより良いものにしようというスタッフ間での意識の浸透を感じました。

心残りは、発表終了直後も余裕がなかったせいもあり、@hirokikyさんに「DjangoCongress JPを開催してくださってありがとうございます」と直接お伝えできなかったことです。かわりにこの場にて感謝申し上げます。

 
ところで、Djangoと自分について振り返ってみると、自分がDjangoを本格的に始めたのは2015年8月くらいだったようです。
Python + Django + Highcharts + Herokuで食べたリンゴの割合をグラフ化してみた - メモ的な思考的な

当時は今よりもさらに日本語の情報が少なく、公式チュートリアルやQiitaのDjango入門、「Two Scoops of Django」本での独学でした。

それから時は流れ、Python + Djangoメインの会社に転職し、仕事で本格的にPythonDjangoができるようになり、Django入門の著者と一緒に働いています。そして、今回のDjangoCongress JP 2018で発表と、Djangoでの縁がいろいろとつながっています。

そのDjangoのカンファレンスにて、Djangoコミュニティに少しでも何かを返すことができたのであれば何よりです。

 
というところで、以降は当日のメモです。

 

オープニング

Chairpersonの@hirokikyさん

資料:DjangoCongress 2018 Opening - Google スライド

PyCon JP 2017の

Why don’t you make a Conference for Django?

からすべてが始まったんだなと感じさせてくれる良いオープニングでした。

また、Code of Conductにもふれられており、とても大切にしているということが伝わってきました。

 

できる!Djangoでテスト!

tell-kさん

資料:できる!Djangoでテスト!

自分のDjangoのテストの書き方で本当にいいのか分からなくて参加しました。

テスト全般〜Djangoのテストまで、いろいろとまとまっていて参考になりました。

特に、

が自分にとっての新しい発見でした。

また、モックのパッチでのハマるポイントについては、過去の自分に教えてあげたい感じでした。

 

GeoDjangoではじめる地理空間情報

小俣 博司さん

資料:GeoDjangoではじめる地理空間情報 // Speaker Deck

元々地図に興味があったのと、以前Open Street Mapの勉強会に参加したことがあり、Djangoと地図ってどういう関係なんだろうと思い、参加しました。
第38回 #NSEG OpenStreepMapマッピングパーティ in 小諸 に参加してきました - メモ的な思考的な

プレゼンは、地理空間情報に関する細かな内容でした。いろいろな用語が散りばめられ、入門する時のよい資料となりそうでした。

あとは印象に残ったところを自分のTweetから転記しておきます。

  • ORMで空間演算
    • 空間演算関数をSQLに組み込んでいる
  • DjangoとOpen Street Mapを結び付けられる
  • WebGISが流行ってきている
  • 測地系と座標系
  • 座標の表現方法は何種類もある
  • Google Mapはメルカトル図法
    • 南極と北極を表現せず、割り切っている
  • 地図情報、ファイルにもいろいろと種類がある(ベクトルとラスタ等)
  • シェープファイルGIS業界のデファクトスタンダード
    • 日本語の文字情報はShift_JISが比較的多い
  • GeoJSON、RFC化されてる。RFC7946
  • PostGISの情報が多い。慣れなうちはこれを使うと良い
  • 最初にためしてみるなら、Leaflet.jsがおすすめ。ただし、Google Mapに感しては、いろいろ複雑
  • 古い地図は、地理院地図が良い
    • 大正時代など、昔のデータも揃ってる
  • Djangoに統合されているため、コンソールにモデルの形式が定義されて表示される
    • modelを作るのが楽で良さそう
  • GeoJSONSerializerなんてのもある
  • デモについて
    • リアルタイムで風の流れが見える
    • つぶやきの場所が見える
  • 地図データ、よく知らないだけでいろいろなものが公開されてる

 

Building your MVP with Django: Lessons Learned Building and Launching a SaaS

James Van Dyneさん

資料:Building your MVP with Django: Lessons Learned Building and Launching a SaaS // Speaker Deck

MVP(Minimum Viable Product)な書き方が気になったので参加しました。

  • ManyToManyFieldを、throughを使うようにする
  • クラスベースビューを避ける
  • テンプレートでは、(余計な)include()ではなくインラインにする

あたりが印象に残りました。

今まで何でもクラスベースビューにしていましたが、必要に応じて関数ベースビューも、と考える良いきっかけとなりました。

 

Djangoにおける認証処理実装パターン

Masashi Shibataさん

資料:Django における認証処理実装パターン - c-bata web

認証処理のカスタマイズに興味があったため、参加しました。

発表の詳細は上記ブログに掲載されているため、ここではその中でも印象に残ったものを記載します。

  • Djangoの認証機能が表にまとまっていた
  • 他の人のライブコーディングを見ると、いつもどんな風に操作しているのか参考になる
    • こんなこともできるなど
  • カスタムユーザモデルは、プロジェクトの開始直後くらいでやっておくとマイグレーションで苦しまない
  • Userモデルのusername、Python3だとunicodeを受け入れてしまう
    • ASCIIUsernameValidator を使うと良い
  • unicodedata.normalize() で、表現を正規化できる

 

Django REST framework 実践入門

Masataka Araiさん

資料:Django REST framework 実践入門 - slideship.com

最近Django REST frameworkにさわっていたのですが、まだ雰囲気でしか使っていないので参加しました。

  • まずはSerializerをおさえる
  • Command-Query分離の原則
    • 入力用と出力用のSerializerを分ける
  • サードパーティライブラリの紹介が、入門者にとっての道案内になっていて助かった
    • drf-writable-nested
    • djangorestframework-camel-case
    • drf-nested-routers
    • django-silk
    • django-js-reverse
  • 質疑応答の方々がみんな使っているばかりで、どんな点に悩むのかが分かった

 

LT

全部で5つのLTがありました。どれも楽しめました。

Python Web History

aodagさん

PythonのWebフレームワークの歴史に関するLTでした。

歴史的経緯などが分かりやすくまとまっていました。Werkzeug(2007)のあとにFlask(2010)が登場したというのが収穫でした。

 

Python out LOUD podcast

ケビンさん

Pythonpodcastに関するLTでした。

いろいろなpodcastがあり、英語を学ばないとなーと改めて感じました。

 

Djangoの同人誌を書いた話

akiyokoさん

資料:Django の同人誌書いた話

 / Kiso Django at techbookfes4 // Speaker Deck

技術書典4で頒布されたDjangoの同人誌についてのLTでした。

同人誌執筆の裏側が見えました。あと、LT資料の中に自分のTweetが引用されていて嬉しくも恥ずかしい気持ちになりました。

また、LT後に執筆してくださったことへの感謝を直接お伝えできて良かったです。

 

Django Girlsとゆかいな仲間たち

Django Girlsの紹介でした。
Django Girls - start your journey with programming

Django Girlsチュートリアルは良いという認識でいましたが、2018年の開催も全国へと展開していて、いろいろと輪が広がっていくのすごいと感じました。

 

サイボウズ株式会社のコネクト支部より

会場を提供してくださったコネクト支部の紹介と、勉強会会場情報のLTでした。

今回のような素晴らしい会場を無償提供してくださっているとのことでした。

東京会場は会議室っぽくなくて、リラックスした雰囲気で参加できたのでとても良かったです。

 

謝辞

最後に謝辞です。

まずは日本システム技研(JSL)の方々、プレゼンの素振りをはじめ、いろいろとご協力いただきありがとうございました。

特に、このネタならCfP行けると言ってくれた sin_tanaka、当初の資料が入門用なのに分かりづらいと気づかせてくれた pro_proletariat、 想定問答や題材をもらった moonwalkerpoday にはとても感謝しています。

なお、プレゼン資料や発表で分かりにくいところ・誤りがあれば、それは全部自分の責任です。

 
また、会場の提供をしてくださったサイボウズ株式会社さま、素敵な場所をありがとうございました。Room2のバーっぽい雰囲気は、登壇初経験のプレッシャーをやわらげてくれ、とてもやりやすくなりました。

 
最後になりましたが、DjangoCongress JP 2018のスタッフ、発表者、参加者のみなさま、ありがとうございました。楽しい時間を過ごせました!

*1:お名前を聞きそびれ、申し訳ないです...

「現場で使える 基礎Django」を読みました #技術書典

最近Djangoを使う人も増えてきているようで、自分がさわり始めた頃に比べれば、分からないことことでも探せば出てくるようになりました。

とはいえ、Djangoの全体像をさらっとながめられるようなものがあまりなく、自分のDjango自体の理解が正しいのか悩んでいます。そのため、Djangoの公式ドキュメントとは異なった視点のものがほしいなと思っていました。

 
そんな中、先日の技術書典4にて「現場で使える 基礎Django」が頒布されると聞いたため、入手して読んでみました*1

Django自体の解説書がほしかった自分にとっては、本書はニーズに合った本であり、とても満足できました。

以下、簡単に感想やメモを残しておきます。

 
ちなみに、今はBoothでも販売されているようです。
現場で使える 基礎 Django【紙の本】※部数限定 - あきよこブログ(akiyoko - BOOTH(同人誌通販・ダウンロード)

 

本の対象読者と自分

本書のp7を引用すると、対象読者は

  • Pythonの文法はある程度分かるけどDjangoは初めてという初心者の方
  • Djangoを始めてみたけれど今いちコツが掴めないという初級者の方
  • Djangoのベストプラクティスを学びたいと考えている中級者の方

とのことです。

ちなみに、自分の経験は

です。

 

感想

本書では、Djangoの基礎的なところからちょっと深いところまで、アプリを作る上で必要そうな範囲がまとめられていました。

書籍全体を通して図を使って解説されていました。特に、

をはじめとした、「Django公式ドキュメントには書いてあるけれど、図がほとんどないのでイメージがわかない」ものに対して処理フローが書かれていました。

そのため、あまり気にせず使っていたり、処理フローがぼんやりしている分野について、理解を深められました。

 
例えば、昔、バリデーションの処理フローを調べたことがありました。
Djangoで、CreateViewでPOST後に動作する、ModelFormやModelのバリデーションを試した - メモ的な思考的な

Blogではフローを図に書き起こしていなかったため、あとから読み返すと理解しづらいなと感じていました。

そんな中、本書にバリデーションフローの図が掲載されていたため、「ほしかったのはこれだ」となりました。

 
また、自分の理解が浅かった

  • モデルマネージャーとその役割
  • INSTALL_APPSの書き方
  • ロギングの設定

なども学べて良かったです。

 
その他、良いと感じたところは、

  • 理由とともにベストプラクティスが掲載されており、他の人の考え方を学べたこと
  • 本に従ったサンプル実装が著者のGitHubで公開されていたため、実際のアプリではどんな感じで実装しているか見られたこと
  • 全体を通して、クラスベースビューを使っていたこと *3

です。

 
執筆後記にも書かれている通り、本書に掲載されていないことはまだまだあります。ただ、検索するためのキーワードは本文中に散りばめられているため、あとから調べる時に役に立ちそうです。

 
一方、注意すべきことは、この本はチュートリアルではないということです。

そのため、自分のように「まずは何か書いてみて概要をつかみ、後で公式ドキュメントを読んで理解する」タイプの人は、本書を読む前に、Djangoの公式チュートリアルDjango入門を行っておくと、理解が深まるのかなと感じました。

 
これからもDjangoをさわる機会はあるかと思います*4。ただ、日々Djangoにさわっていないと忘れてしまう内容もあるため、Djangoアプリを作るときには手元に置いて参考にしたいと思います。

id:akiyoko さん、良い本をありがとうございました。

*1:技術書典4自体の参加記録:http://thinkami.hatenablog.com/entry/2018/04/24/224740

*2:Django入門の著者である同僚も、この本を購入していました

*3:自分は関数ベースビューがよく分からないので...

*4:仕事で使えると最高ですね!

技術書典4に行ってきました #技術書典

4/22に秋葉原UDX アキバ・スクエアで開かれた、技術書典4に行ってきました。

techbookfest.org

 
イベント自体は知っていたのでいつかは行きたいなーと思っていました。そんな中、日本語で書かれたDjango本「現場で使える基礎Django」が頒布されると聞いたので、行くことにしました。

 
ただ、このようなイベントには初参加であり、勝手がよく分かりませんでした。そのため、事前に公式ブログや参加のチュートリアル的なブログを読んでおきました。

 
当日は現地でkobayutaponさんと合流し、会場入りしました。

整理券が配布されると聞いていたので、早めに行ったところまだ配布されていませんでした。そのため、ヨドバシカメラでうろうろしていたら、整理券が配布されました。

会場に向かうとすでに多数の人が並んでいて、整理券をもらうのにもしばらく待ちました。自分たちは500番台でした。

 
開始まで時間があったため、またヨドバシカメラでうろうろしていました。しばらくすると入場開始のお知らせがあり、会場へ向かいました。整理券を受け取ったときよりも待機列が伸びていたので驚きました。

 
整列して入場し、まずは「現場で使える基礎Django」を購入しました。

人が多くて会話できませんでしたが、Djangoの本を執筆してくださってありがとうございますという気持ちでした。

 
その後は同僚に頼まれた本を購入したり、気になる本を探して会場をうろうろしていました。入り口でトートバックをもらったため、人が多い中でも本の持ち運びがしやすく助かりました。

当日の戦利品はこちらです。

 
また、ポスターもいただきました。今はギークラボ長野に貼ってあります。

 
お昼前に会場を後にして、技書話人伝へ行きました。
技書話人伝

こちらはゆったりと本を見れました。技術書同人誌展示コーナーも楽しめました。

その後、お昼ごはんを食べたり、低レイヤーのお店めぐりをしました。低レイヤーはあまり詳しくないので、kobayutaponさんの解説はありがたかったです。

 
最終的には2万歩くらい歩いて身体に疲労感がありましたが、熱量あふれる技術書を見るのは楽しく、良い一日でした。また、技術書を書くのも面白そうだなーと感じました。

運営者・サークルのみなさま、ありがとうございました。

「OSSライセンス」勉強会に参加しました #nseg #glnagano

4/21に、ギークラボ長野にて開催された「OSSライセンス」勉強会に参加しました。
「OSSライセンス」勉強会 - connpass

 
テクニカルライター/ITライターの可知豊さんの講演の他、フリーテーマのLTがありました。

昔、ライセンスまわりを調べていた時、可知さんの書籍に出会って非常に助かったため、当日を楽しみにしていました。

ライセンスまわりは何となく理解していましたが、OSS著作権の関係をすっかり忘れていたため、色々と学べて良かったです。

 
以下簡単なメモです。誤っていたらご指摘ください。

 
目次

 

オープンソースライセンスの基礎と実務(ダイジェスト版)

スライド:オープンソースライセンスの基礎と実務

スライドのダイジェスト版の講演でした。重要と思われるところを中心に話していただいて、理解しておいたほうが良いポイントが分かりました。

印象に残ったところは以下です。Tweetできなかったところは他の方のTweetを引用します。

 
また、最近、趣味で機械学習のモデルを作っていたため*1、作ったモデルのライセンスに関する質問をしてみました。

という回答をいただけました。

 
他に、可知さんにサインをいただきました。ありがとうございました。

 
なお、書籍の最新版は電子書籍にて提供・販売されています。内容も適宜更新されるそうなので、こちらをどうぞ*2
知る、読む、使う! オープンソースライセンス - 達人出版会

 

LT

フリーテーマでしたが、いずれも(資格試験含む)ライセンスまわりのLTでした。

 

AWS認定ソリューションアーキテクトアソシエイト取得への道 (katekichiさん)

LTを聞いて、地道に勉強するしかないと感じました。

業務で学んだことが出題され、資格勉強で得た知識を業務にいかせているとのことでした。

 

MySQLのライセンス (とみたさん)

スライド:MySQLのライセンス

MySQLのライセンスまわりについてのLTでした。

  • MySQL本体のライセンス(GPLと商用)
  • クライアントライブラリのライセンス(GPL)
  • ライセンスの関係上、MariaDBの機能をMySQLの商用には取り込めない

が印象に残りました。

 

とある実例

とある実例のお話でした。

「やってしまったのは仕方ない、正直に対応する」というのが印象に残りました。大事。

 

農業AIアイデアソンに参加してきた (kotyさん)

スライド:農業AIアイディアソンに参加してきた // Speaker Deck

当初の予定とは変更し、農業AIアイデアソンに関するLTでした。

いつもリンゴは食べる側でしかなく、栽培については書籍でちらっと知った程度なので、現場のお話がちらっと聞けて良かったです。

また、農業における暗黙知形式知にするのは、大変だけど重要そうだと感じました。

 

その他

受付係をしました。出席率100%でありがたいことです。

お菓子係も行いました。当日暑かった & 前回担当より参加者多かったため、飲料とお菓子を1セットずつ増やしました。

ただ、ちょっと量が多かったかもしれませんので、ここらへんはまた担当する時に考えたいと思います。

 
最後になりましたが、可知さんをはじめとする関係者のみなさま、ありがとうございました。

*1:http://thinkami.hatenablog.com/entry/2018/04/16/080742

*2:Amazonを見たらプレミアムがついていて驚きました...

Recap of TensorFlow Dev Summit 2018 in 信州 に参加しました & LTしました #tfug #GDG信州

4/13(金)に塩尻インキュベーションプラザ(SIP)で開催された、Recap of TensorFlow Dev Summit 2018 in 信州 に参加しました。
Recap of TensorFlow Dev Summit 2018 in 信州 - connpass

資料はconnpassの他、当日の様子がTogetterにまとめられています。
Recap of TensorFlow Devsummit 2018 in 信州のまとめ - Togetter

最近、機械学習にふれており、TensorFlowまわりの近況を知りたくて参加しました。

以下メモを残しますが、誤りがあればご指摘ください。

 
目次

 

全体俯瞰及びTensorflow.js (adamrockerさん)

まずTensorFlow Dev Summit 2018の全体的な話がありました。

現地では1セッション15分、しかもいずれも延長が無いという濃密なものだったようです。

全体俯瞰で気になった内容は以下でした。

  • TensorFlow HUBで学習モデルが提供される
  • tf.kerasに統合されていく
  • Estimator推し
  • tf.data
  • 前処理まわり
  • AutoMLでのモデル構築
  • CSVも1.8から対応

 
引き続き、Tensorflow.jsのメモです。

  • Tensorflow.js + ブラウザで、機械学習・ファインチューニングと訓練済モデルの移植ができるようになる
    • ユーザに特化した体験を提供する時に、ブラウザの学習を使う
  • Tensorflow.jsで画像を認識させるには、imgタグを使えば良い
  • Separable Convolution
  • 今年のGoogleのエイプリルフールの舞台裏では、Tensorflow.jsが使われていた
    • 方向分解特徴や時間的特徴の利用

 
その後、ブラウザ(TensorFlow.js)と、モバイル(TensorFlow Lite)の画像認識デモがありました。

  • 訓練画像80件でそれなりの精度が出ていること
  • リアルタイムで画像認識し、リアルタイムに類似度を更新

を実体験できて良かったです。

 
今後も、理論を学びつつ、ツールの使い方も学んでいかないとなーと思いました。

 

TensorFlowを使ってみる (kobayutaponさん)

TensorFlowのチュートリアル後の簡単な例を、体験を交えながらの発表でした。

正弦波・矩形波を使ったTensorFlowチュートリアルのような内容で、さくさくとモデルができていったのが印象に残りました。

電子工作系ではこんな感じでデータを取るのかと参考になりました。

 

自分のための機械学習をしてみた話 (thinkAmi)

自分のLTです。

 
枠が空いていたこともあり、せっかくなので最近やっていたことをLTしました。

内容は「Google Drive APIによるOCR & Doc2Vec を使って、IPA過去問の類似度を出す」です。

会場に来ていた方に質問したところ、

と、なかなか緊張する中でのLTでした。

 

GDG信州分科会 (LED信州)

GDG信州分科会として、電子工作勉強会グループ「LED信州」を立ち上げるというLTでした。

一人で電子工作していても詰まってしまうところがあるので、身近にこのような勉強会があるのはありがたいです。

 

パネルディスカッション

kehiさんや会場からの質問に対して、adamrockerさん・kobayutaponさんが回答するという形でのパネルディスカッションでした。

会場からもマニアックな質問などが出ていて、いろいろと盛り上がりました。

GDG信州のイベントではパネルディスカッションがあることが多く、いろいろな方面からの質問や回答を聞けて良いです。

 

次回予告

GDG信州のイベントの予告がありました。

 
最後になりましたが、開催してくださった関係者のみなさま、ありがとうございました。

Python3 + google-api-python-clientで、Google Drive APIを使ってpdfファイルをアップロードし、OCR処理をする

手元の画像pdfファイルをOCR処理したいことがありました。

手軽にOCR処理する方法がないかを調べたところ、Google DriveOCR機能があることを知りました。
GoogleDriveのOCR機能を使って、大量の画像ファイルをテキストに変換する

そこで、Google DriveOCRを試してみることにしました。

 
なお、上の記事ではgdirveというCLIツールを使っていました。
prasmussen/gdrive: Google Drive CLI Client

PythonGoogle Drive APIを使ってみたかったので探してみたところ、 PyDrive がありました。
gsuitedevs/PyDrive: Google Drive API Python wrapper library

ただ、今回はファイルをアップロードするだけで複雑なことはしないため、Google APIPythonライブラリ google-api-python-client だけでGoogle Drive APIを使ってみます。
google/google-api-python-client

 
目次

 

環境

 
なお、画像としてpdf化されたファイル例として、今回は情報処理試験の過去問を使ってみます。
IPA 独立行政法人 情報処理推進機構:過去問題

今回は、基本情報処理試験の午前問題である 2017h29a_fe_am_qs.pdf を使います。

最終的なディレクトリ構造は以下となります。

$ tree
.
├── 2017h29a_fe_am_qs.pdf
├── __init__.py
├── client_id.json
└── google_drive_ocr_uploader.py

 

Google Drive APIを使うための事前準備

Python Quickstartを参考に、事前準備を行います。
Python Quickstart  |  Drive REST API  |  Google Developers

プロジェクトの作成まわりは、以前のGmail APIの時と同様で良さそうです。
Python3 + google-api-python-clientで、Gmail APIを使ってメールを送信する - メモ的な思考的な

 
認証情報が含まれる client_id.json ファイルは、実行用スクリプトと同じディレクトリに入れます。

 

調査事項

認証まわり

公式ドキュメントの get_credentials()関数まわりを使用します。
Step 3: Set up the sample - Python Quickstart  |  Drive REST API  |  Google Developers

なお、Python2.6関係のソースコードは削除しました。

 
Scopeはどうしようかと思いましたが、公式ドキュメントに

Per-file access to files created or opened by the app. File authorization is granted on a per-user basis and is revoked when the user deauthorizes the app.

https://developers.google.com/drive/v3/web/about-auth#OAuth2Authorizing

とあったため、 https://www.googleapis.com/auth/drive.file を使うことにしました。

 

アップロードする時のMIMEタイプについて

どのようなMIMEタイプにすればよいか見たところ、

The extracted text will appear in the Google Docs document alongside the embedded image.

https://developers.google.com/drive/v3/web/manage-uploads#importing_to_google_docs_types_wzxhzdk18wzxhzdk19

とありました。

ドキュメントにある表より、pdfの場合はGoogle DocsにするMIMEタイプを指定すれば良さそうでした。

Google DocsMIMEタイプは application/vnd.google-apps.document でした。
Supported MIME Types  |  Drive REST API  |  Google Developers

 

ocrLanguageの設定先について

OCRをどの言語で実行するかについては、 ocrLanguage に設定すれば良さそうでした。
Files: create  |  Drive REST API  |  Google Developers

ライブラリのドキュメントを読むと、create()メソッドの引数に ocrLanguage がありました。
https://developers.google.com/resources/api-libraries/documentation/drive/v3/python/latest/drive_v3.files.html

OCR言語コードは ISO 639-1 codeで指定すればよいので、日本語の場合は ja とします。

 

bodyパラメータで指定するファイル名について

アップロードするファイル名を指定します。

Google Docsにするからといって拡張子を外すと、以下のようにHTTP 400エラーが発生しますので、拡張子をつけたままにします。

googleapiclient.errors.HttpError: <HttpError 400 when requesting https://www.googleapis.com/upload/drive/v3/files?ocrLanguage=ja&alt=json&uploadType=resumable returned "Bad Request">

 

実装

google_drive_ocr_uploader.py

import argparse
import os
import pathlib

import httplib2
from apiclient import discovery
from googleapiclient.http import MediaFileUpload
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage


UPLOAD_FILE_NAME = '2017h29a_fe_am_qs.pdf'
MIME_TYPE = 'application/vnd.google-apps.document'
SCOPES = 'https://www.googleapis.com/auth/drive.file'
CLIENT_SECRET_FILE = 'client_id.json'
APPLICATION_NAME = 'ipa-google-drive-api-client'

flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()


def get_credentials():
    """Gets valid user credentials from storage.

    If nothing has been stored, or if the stored credentials are invalid,
    the OAuth2 flow is completed to obtain the new credentials.

    Returns:
        Credentials, the obtained credential.
    """
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir,
                                   'drive-python-quickstart.json')

    store = Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        credentials = tools.run_flow(flow, store, flags)
        print('Storing credentials to ' + credential_path)
    return credentials


def upload_with_ocr():
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('drive', 'v3', http=http)

    local_file_path = pathlib.Path(__file__).resolve().parent.joinpath(UPLOAD_FILE_NAME)

    media_body = MediaFileUpload(local_file_path, mimetype=MIME_TYPE, resumable=True)

    body = {
        'name': local_file_path.name,
        'mimeType': MIME_TYPE,
    }

    service.files().create(
        body=body,
        media_body=media_body,
        ocrLanguage='ja',
    ).execute()


if __name__ == '__main__':
    upload_with_ocr()

 

実行結果

$ python google_drive_ocr_uploader.py 

と実行後、自分のGoogleドライブの直下のディレクトリを見ると 2017h29a_fe_am_qs.pdf ファイルが存在します。

ファイルを開くとOCR結果が表示されました*1

複数ページのpdfでも、全ページOCR処理がなされていました。

 

ソースコード

GitHubに上げました。 google_drive_api ディレクトリの中にあるものが今回のファイルです。
thinkAmi-sandbox/google-api-python-client-sample

*1:掲載してよいのか分からないため、結果は省略します