Python3 with djangoでエクセルで文字化けしないcsvをダウンロードさせる
よくあるcsvダウンロード機能ですが、エクセルで開くことを想定して作らなければいけないケースが多々あると思います。
今回、エクセルで開いた時に日本語が文字化けしないcsvのダウンロード機能をpythonで書いてみます。
使っているフレームワークはDjango。
標準のcsvモジュールだとunicodeがサポートされていないとのことなので、unicodecsvを使います。
GitHub - jdunck/python-unicodecsv: Python2's stdlib csv module is nice, but it doesn't support unicode. This module is a drop-in replacement which *does*. If you prefer python 3's semantics but need support in py2, you probably want https://github.com/ryanhiebert/backports.csv
unicodecsvはpipでインストールできます。
pip install unicodecsv
基本的には標準のcsvモジュールと似ていますね。
from django.http import HttpResponse import unicodecsv as csv def csvdl(request): ret = HttpResponse(content_type="text/csv") ret["Content-Disposition"] = "attachment; filename=name.csv" w = csv.writer(ret, encoding='cp932') w.writerow(["あいう", "えお", ...]) return ret
encoding='cp932'を使えるところがミソ!!
Buttonタグで勝手にsubmitされる件
ハマった!!!
djangoでajaxしようと思ってカリカリ書いてたら何度やっても画面のリロードが走る。
これはdjangoの変な仕様だと決めつけてcsrfらへんを必死に調べたけど手がかりなし。
かれこれ1時間半くらい経った時に、ふと昔同じような件でハマったのを思い出す。
原因はButtonタグの仕様で、Buttonタグはdefaultでtype="submit"になるとのこと。
type="button"(汎用ボタン)にすることで無事ajaxが走る。
Buttonクリック時にeventを受け取ってevent.preventDefault();でデフォのsubmitをキャンセルしておけば、
type="submit"でも同じ動きになる。(type="submit"にする意味ないけど)
ってか2ヶ月位前にこの仕様でハマったにもかかわらず、同じことを繰り返してた
自分にめちゃくちゃ腹が立ったというお話でした。。。
django、疑ってすまん。
PythonのAnacondaってどうなん??
気軽にscrap and buildできるPython3の汎用開発環境を作りたいと思ってDockerfileを書いてみました。
dockerfile-for-python-proto/Dockerfile at master · kentaro-a/dockerfile-for-python-proto · GitHub
Pythonあまり触ったことないのでモジュルやら何やら詳しくないのですが、
Python-3.5.1をソースからインストールしてpip,pandasその他を入れるみたいなことをやってる。。
Tensorflow触ってみたいので↑から作ったコンテナでインストールしようとしたものの、
依存モジュール絡みでもんのすごく面倒くさいっぽい。
いろいろ調べていくうちにAnacondaというプラットフォームを発見。
どうやら分析寄りの環境を簡単に構築できるらしい、、、というかPythonの環境管理全般いけるみたい。
pipであくせくするよりもこれで管理したほうがいいんじゃね?と思ったんですが、どうなんでしょうか。。
まあとにかくAnaconda試してみようと思います。
WordPressのAMPプラグインで/ampが真っ白になった件
WordPressのAMPプラグインを入れると一発でAMP化できるらしい、
という噂を聞いて早速試す、、、無事撃沈。
若干ハマったのでメモします。
・使ったプラグイン
AMP — WordPress Plugins
こちらのブログを参考にしたのですが、自分の環境でうまくいきませんでした。
プラグイン公式サイトのFAQに同じ質問が挙がっていたものの、未解決でした。。
WordPressのプラグインでブログをAMP対応にしてみた | 海外SEO情報ブログ
あれこれ調べた結果、サーバにphp-xmlがインストールされていなかったため、
プラグインのモジュール内でDomDocumentクラスが使えずに落ちていたことが原因でした。
WordpressのconfigでdebugモードをONにしてエラーを出してみると、
DomDocumentクラスが使えないみたいなメッセージがしっかりと出てました。
yum -y install php-xml service httpd restart
ちなみに、AMPプラグインでは現状投稿ページしかAMP対応できないそうです。
AMPのバリデートエラーもブラウザの機能でチェックできるようです。
詳しくはこちらで紹介されています。
検証!AMPに沿ったマークアップとエラーチェックの方法をご紹介! | サクラサクLABO公式ブログ
ヤレヤレ。。
mysqlでtinyintがbooleanになる件
mysqlでtinyint(1)を指定したカラムのデータをcakephp3のモジュールで取得した際に、booleanとして扱われて困った。。
mysqlのバージョンは5.6.27
cakeのバグか?とも思ったんですが、リファレンスを見てみるとちゃんと書いてあった!
・BOOL、BOOLEAN
These types are synonyms for TINYINT(1). A value of zero is considered false. Nonzero values are considered true:
MySQL :: MySQL 5.6 Reference Manual :: 11.1.1 Numeric Type Overview
mysqlではbooleanはtinyint(1)のシノニムであり、0はfalse、0以外はtrueとして評価するとのことなので、cakeはtinyint(1)の値をbooleanに変換して処理してしまうようです。
ただ、実際にtinyint(1)には-128~127の整数値を入れられるので、ハマってしまう人も多いのではないでしょうか。
PHP7三項式まわりが快適すぎる
PHP7の三項演算あたりを本格的に使ってみましたが、快適すぎてやばいです!
あるkeyが存在するかどうかわからない配列をマージするような場合、
いちいちisset()しなくてよくなった!!
array_merge( $a['key'] ?? [], $b['key'] ?? [], $c['key'] ?? [], $d['key'] ?? [] );
isset地獄にみなさん1度はハマったことがあると思いますが、
PHP7だとスッキリしますね。
【Ruby】ChatworkAPI for Ruby
前回、ChatworkAPIクラスのPHP版を公開しましたが、今回Ruby版も作りました。
class Chatwork # イニシャライズ # apiToken: 自身のAPIトークン def initialize(apiToken) tokenHeaderKey = "X-ChatWorkToken: " @apiToken = apiToken # APIトークン @reqHeader = "X-ChatWorkToken: #{@apiToken}" # リクエストヘッダ @room = getRooms(); # ルームID end # ルーム一覧取得 def getRooms() ret = {} uri = URI.parse("https://api.chatwork.com/v1/rooms"); # httpクラス http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE # httpリクエスト情報オブジェクト request = Net::HTTP::Get.new(uri.request_uri) request.add_field("X-ChatWorkToken", @apiToken) # httpレスポンス response = http.request(request) # ルーム名:ルームIDのハッシュにする JSON.parse(response.body).each{|data| ret[data["name"]] = data["room_id"] } return ret end private:getRooms # ルーム名からルームIDを取得する # roomName: ルーム名 def getRoomID(roomName) return @room[roomName] end # メッセージを送る # roomid: ルームID # msg: メッセージ def sendMessage(roomid, msg) uri = URI.parse("https://api.chatwork.com/v1/rooms/#{roomid}/messages"); # httpクラス http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE # httpリクエスト情報オブジェクト request = Net::HTTP::Post.new(uri.request_uri) request.set_form_data({'body'=>msg}) request.add_field("X-ChatWorkToken", @apiToken) # ChatworkAPIにpostする http.request(request) end end
使い方も前回同様にAPIトークンを渡してnewし、getRoomIDにメッセージを送信したいルーム名を渡してルームIDを取得、
sendMessageでメッセージを送るといった流れです。
最低限の機能しか実装してませんのでカスタマイズしてみてくださいm(_ _)m