Make組ブログ

Python、Webアプリや製品・サービス開発についてhirokikyが書きます。

DjangoのField.__init__ でクエリーしてはいけない

動的にフォームの choices の値を作りたい場合など、フォームの内容のためにクエリーすることはよくあると思います。 でも、フィールドの __init__ でクエリーしてしまうコードを書くとインポート時に実行されてしまうので注意が必要です。

ダメな例

class FoobarChoiceField(forms.ChoiceField):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.choices = [(foobar.name, foobar.title)
                        for foobar in Foobar.objects.all()]


class HogeForm(forms.Form):
    foobar = FoobarChoiceForm()

理由

フィールドの __init__ はインポート時に実行されてしまうので、インポート時に(上記の場合Foobarへの)クエリーが実行されてしまいます。 インポート時にHogeFormが作成されて、FoobarChoiceField.__init__ も実行されます。 choicesがリストの場合、そのままクエリーも実行されてしまいます。

マイグレーション時(DBが作られる前)などに実行されてしまうとFoobarに対応するテーブルがまだ作られていないのでエラーになります。 また、サーバー起動時にクエリーされる場合、DBに変更があってもchoicesの値が変わらなくなってしまいます。

直す例

Django1.8からchoices指定にcallableを渡せるので、callableにしておきましょう。

class FoobarChoiceField(forms.ChoiceField):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.choices = lambda: [(foobar.name, foobar.title)
                                for foobar in Foobar.objects.all()]

もちろん、フィールドを作らない場合はFormでやってもOK。 まぁFormの __init__ は(普通に書く分には)インポート時に呼び出されないので、1.8以前のように __init__ で choices を作るように書いてもOKです。

class HogeForm(forms.Form):
    foobar = ChoiceForm(choices=lambda: [(foobar.name, foobar.title) for foobar in Foobar.objects.all()])

Ubuntu 18.04 をインストールして「grub-efi-amd64-signedパッケージを/target/にインストールするのに失敗しました」で落ちる

Ubuntu 18.04 を Windows 10 とデュアルブートしようと設定しているときに grub-efi-amd64-signedパッケージを/target/にインストールするのに失敗しました というエレーが発生してインストールできなかった。

2018-07-17時点での話。

解決した方法

Wifiを設定せずにインストール。

サードパーティ製パッケージのインストールは有効で、セキュアブートは無効にしていた。 パーティションはマニュアルで設定したけど、とくに普通のext4/ と、スワップを設定したのみ。

なぜか知らないけどこれでうまくいった。 Wifiをつなぐとインストーラーやらが最新になって何かしらのバグを踏むとかなのだろうか。。。

見た情報、試した方法(でも解決にはならなかった情報)

/boot/efi パーティションを自作して解決する方法はうまくいかず。 Windows Boot Managerと場所が被るとかで設定できなかった。

www.geek.sc

VMUbuntuは入れなかった

やっぱりデュアルブートにしたかった。 WindowsをホストマシンにしてVMでプログラミング環境をUbuntuで起動しても良いのだけど、 やっぱりWindowsを使うというのが苦痛で仕方なかったのでデュアルブートすることにした。

factory-boyとDjangoでテストを書くときにファイルをうまく使う

ORMってファイルが入ると途端にめんどくさくなるよね。

まして単体テストで都度物理的なファイルを扱ったりするのはもうめんどくさすぎます。 でも factory-boy を使えばDjangoのFileFieldやImageFieldも楽に使えます。

バージョン

factory-boy==2.11.1 でやってます。

使い方

こんな感じで ImageField を持ったモデルで説明します。

from django.db import models


class Book(models.Model):
    cover_image = models.ImageField("カバー画像", ...)

factory-boyをこんな感じで書きます。 factory.django.ImageField を設定しておきます。

import factory


class BookFactory(factory.django.DjangoModelFactory):
    cover_image = factory.django.ImageField()

    class Meta:
        model = models.Book

そうすれば cover_image__ のように __ に続いて指定できます。 この例だと自動で作る画像の色とファイルの名前、サイズ、画像の拡張子を指定しています。

        book = BookFactory(
            cover_image__color='green',
            cover_image__format='PNG',
            cover_image__height=10,
            cover_image__width=10,
            cover_image__filename='test.png',
        )

いちいち物理的なファイルやら django.core.files.base.ContentFile やらも使わずに書けて便利。 この factory.django.ImageField__init__ に渡せる引数を、 __ 経由で渡せるようです。

Using factory_boy with ORMs — Factory Boy latest documentation

factory.django.FileField の場合は __data でバイナリーを指定できます。 すごく便利。

factory-boyについてはPythonプロフェッショナルプログラミングの14章にも書いたのでぜひ読んでみてください。

Pythonプロフェッショナルプログラミング 第3版

Pythonプロフェッショナルプログラミング 第3版

AWS上のデプロイ用インスタンスからPackerでAMIビルドしたらPackerBuilderにSSHできない問題を解決した話

Packer が好きで使ってます。 AWSのAMIをビルドするために使ってるんですが、そこであった話。

構成

デプロイ用のインスタンスから packer build してAMIを作る。

  • PackerBuilderには既存のSecurityGroup(セキュリティグループ)を指定する
  • PackerBuilderはPublicAccessを受け付ける
  • ParkerBuilderには既存のSSHキーペアを指定する

この既存のSecurityGroupは「デフォルト」のSecurityGroupで、このSecurityGroup自身からのアクセスを受け付けるようにしています。 デプロイ用のインスタンスも、PackerBuilderも同じSecurityGroupに所属させることでアクセスを許可しようという狙いです。

起こったこと

packer build 中にSSH接続できない

原因と理由

PackerはデフォルトでパブリックIPを使って接続しようとしていたのが原因(PackerBuilderでPublicAccessを受け付けるようにしていたからかな)。 SecurityGroupは パブリックIPを通して接続すると、「特定のSecurityGroupからのアクセス」と特定できなくなってしまう ので、単なる外部アクセスと判断されてSSHが拒否されていた。

ローカルIPを直接使うか、パブリックDNS(Public DNS)を使えば、EC2インスタンス上からIPを引けばローカルIPが取得できるのでアクセスできる (正しく特定のSecurityGroupからアクセスがあったと判断してもらえる)。

解決方法

packer.json"ssh_interface": "public_dns" を指定して、パブリックDNSを使ってSSH接続するようにした。

  "builders": [
    {
      "type": "amazon-ebs",
      ...
      "associate_public_ip_address": true,
      "security_group_ids": ["<デフォルトSecurityGroup>"],
      "ssh_keypair_name": "...",
      "ssh_private_key_file": "...",
      "ssh_interface": "public_dns"
    },
  ]

Amazon EBS - Builders - Packer by HashiCorp

デプロイサーバー上でパブリックDNSを引けばローカルIPが引けるので問題なし。 まぁ、 "local_ip" を指定してもいいんだけど。

Packerのデバッグ方法

Packerのログを見るときはPACKER_LOG=1 をつけて実行すると良い。 実行している内容とかが標準出力ででる。

$ PACKER_LOG=1 packer build ...

あと packer build -debug ... とオプションを付ければステップ実行できる。 便利よ。

$ PACKER_LOG=1 packer build -debug ...

www.packer.io

動かないときは色々試す前に原因見つけような! ログがしょっぱいツールとかシステムのときは仕方ないけどね。

結構ハマったって話

デプロイサーバー上からもローカルからもPackerBuilderにSSHできるので原因が分からなかった。 デバッグ出力するとどうやらパブリックIPでつないでいるようだったので、これが原因だとわかった。

SecurityGroupはローカルIPで繋がないと、「SecurityGroupからアクセスがあった」と特定できないっていうのは気をつけないとね。

自宅の開発環境(オフィス)を整備した話、机とかキーボードとか

自宅の開発環境を整備したので、そのお話をします。 わりと個人的な話ですが、買った机などは読んだ人が買うときの参考になれば嬉しいです。

なんで自宅の環境を整備しようと思ったか

貯蓄と資産運用のおかげもあって、ある程度まとまったお金ができました。 開業資金として最低限の目標としていた額に達して、もう少し資金など準備しつつ、あとは良い時期に良い感じに会社を作れたらなぁという次第です (そこは今の環境で学べることなどを加味して時期を決めれば良い)。

なので単に資産として持っておく以外に、お金を使っていこうかなと考えた次第です。

自宅の開発環境、使う?

会社のオフィスで働いていれば、それほど自宅の開発環境は使わないと思います。 良い環境がほしいときも、コワーキングスペースやカフェにいけば十分と思います。

ですが、僕の働いている BeProud ではリモートワークが週5でできます 。 であれば、自宅の環境をガツンと整備してより仕事をしやすくするのは悪くないと思います。

jobs.beproud.jp

僕は自宅でもプログラミングの機会はかなり多いです。 BeProudと関係ないサイドプロジェクトや、OSS活動、資産運用と、プログラミング・デスクワークになる機会はかなり多いです。 将来的に自宅を事務所にする場合にも、環境が整備済みであれば導入も楽ですしね (こう言っていると物欲を満たす言い訳をしているようですが。。)。

また、日常触れる、使う機会が多いものにお金を使うほど満足度が大きいらしいです。

どんな物にお金をまわす のかというと、シンプルに「毎日・長時間使う物」で いい。 科学的 にも「 毎日長時間 使う物にお金を多く使ったほうが幸福度が高い( = コンフォート 原則)」 ことが立証されている。

ミニマリストしぶ. 手ぶらで生きる。見栄と財布を捨てて、自由になる50の方法 (Kindle Locations 1112-1115). サンクチュアリ出版. Kindle Edition.

手ぶらで生きる。見栄と財布を捨てて、自由になる50の方法

貧乏性なので何かにつけて「そんなん要らんでしょ」と渋りガチなので、こういうとこはガツンと使っていこうと思っています。 ついでに部屋にあった要らないものを捨てたり、デスクの配置換えをして最適化しています。

整備した自宅の環境

デスクまわりの環境はこんな感じです (昔VIPとかであった部屋画像スレっぽいですが。。)。

f:id:hirokiky:20180528163914j:plain

キーボード: Barocco

買いました。初めて使う分割キーボードですが、かなり良いです。 思った以上に肩が楽です。 ErgoDoxとかは値段が高いので、肩こりひどいし分割キーボードどうかなぁ、って人はこのMistel Baroccoで良さそうです。 (キー配列も普通のキーボードのように斜めにズレているので、違和感もなく慣れました)。

僕はHappyHackingKeyboardを良く使っていましたが、使い勝手も良いです。 赤軸というものを使っていますが、タイプ感も良いです。

僕はDvorak配列なので、ハードウェアでDvorakにできるのは安心です。 とはいえ、ソフト側でDvorakにしているのでキーボードはQwerty配列のままです。 新しいVMに接続したときなどはハードウェアでのDvorak配列が活躍してくれるかなと期待しています。

トラックボール: SlimBlade

買いました。LogitechのMarbleMouseというトラックボールを5,6年使っていたので、これも新しいものにしました。 使い勝手はかなり良いですね。最初、独自のスクロールの方法(ボールを横に回す)に慣れませんでしたが、慣れれば使いやすいです。

まぁトラックボールについては投資というよりも、単に欲しかったので買っただけです。

買いました。 幅120cmで、高さが70cm程度ある机を探していました。 探してみると目的にあう机というのは意外となくて苦労しましたが、この机はオススメします。

このポイントを満たす机を探していました:

  • 引き出しがない => 膝が当たらない
  • 大きさが十分ある => 横120cmはほしい
  • 木製で、表面に加工がされている(ガラスは重い)
  • 足が4本の支柱でなく手前側に空間がある
  • 足が木の板でない
    • 無駄に重い
    • 机の横のラックが使いにくくなる
  • 背面に鉄板がついている
    • 強度が安心
    • OAタップが磁石で貼り付けられてスッキリする
  • 1万円程度

意外と、条件を満たす机はないです。3時間くらいずっと探してました。 今の僕ならオフィス用品、デスク環境コンサルにもなれるんじゃないでしょうか。

デスクの広さは言ってしまえばメモリーの量みたいなもんかもしれませんね。メモリー16GBは最低ほしいというなら、デスク幅120cmは最低ほしいところです。 メモリーもデスクも費用対効果が良いので大きくて損はないと思います。

OAタップはコレを買いました。磁石で貼り付くのでスッキリして良いです。

以前からあったもの

  • Bose Sound Link Mini 2: 音楽聴きながら仕事したいので良いです
  • 新しい新しいiPadとApplePencil: アナログノート大好きなので良いです
  • BenQのモニター: 安くて最高
  • MacbookPro(会社支給)

椅子

f:id:hirokiky:20180528164025j:plain

買いました。椅子については悩みに悩みましたが、リクライニング機能があることに重点を置きました。 僕の中で「エルゴノミクス vs リクライニング」という壮大なバトルが勃発しましたが、動画を寝転んでみたりリラックスしたかったのでリクライニングできるものにしました。

この商品にはかなり満足しています。 ですが、仕事でごりごりキータイプするとなると姿勢は崩れがちです。 寝るようにしてコードを書くか、椅子の上であぐらをかいて軽く猫背になるかどうかという姿勢です。

これについてはエルゴノミクスチェアー的なのを買えばよかったかなぁと少し思っています。 (良さそうなのは8万円とか10万円とかでひよったというのもある。。)。

椅子の材質はメッシュにしました。 合皮は加水分解してボロボロになるというのが、BeProudのオフィスの椅子で分かっていたのでメッシュです。

ホワイトボード

f:id:hirokiky:20180528163933j:plain

これは以前から自宅にあったものですが、 AmazonでB級品として買った安いホワイトボード です。 1200x900と大きいですし、重さが5kgあるので壁につけるのは少し苦労します。

ですが、ホワイトボードは大きいほうが良いです。 ホワイトボードは大きければ大きいほど発想も大きくなります。 部屋の壁全面ホワイトボードでも良いです。

壁に貼るホワイトボードシート的なやつはオススメしません。 すぐ汚れが落ちなくなりますし、書きにくいです。一回試しましたが、すぐに汚れが取れなくなったので捨てました。 それなりなホワイトボードを買いましょう。

超どうでも良いですが、ホワイトボードマーカーとイレーザーはこれを使っています。

僕はけっこうアナログ人間っぽいので、手書きのノートとかホワイトボードがあると発想が湧きやすくなる気がします。

おわりに

こんな感じで、自宅開発環境を整備したよっていう話でした。 今回使ったお金は全部で5万円ほどでした。自分なりにかなり気合を入れたわりには安く抑えた印象です (モニターアームと縦置きディスプレイも買いましょうか)。

もし 「これもオススメだよ」、「椅子コレ使ってるよ」とかあったら教えてください

感触としてはかなり良かったなという印象です。我ながらうまくやったと思うのは、事前の検討、採寸をちゃんとしたことです。 机のサイズ、椅子のサイズ、部屋のサイズや空間の配置方法などを、ある程度決めてから買いました。 おかげでほぼ思ったとおりの環境にできました。

正直、ライフハック的なのは全然好きじゃないんですが、なんだかんだそういうことをやっている気がします。 (服をひたすら断捨離して同じものを複数買ったり、ダンボールを捨てて折りたたみコンテナーにしたり、ものを断捨離しまくったり)

余談ですが、冷蔵庫の中もこんな感じで福利厚生が充実しています。

f:id:hirokiky:20180528131214j:plain

会社ではドリンクの支給が(ありがたいことに)ありますが、自宅であれば(自腹ですが)好きなものが揃えられて良いですね。 水は中硬水が良いとか、飲む飲まないに関わらずレッドブルは備蓄しときたいとか、色々めんどうな僕の性格を自宅であれば好きに満たせます。

他のオススメ記事

blog.hirokiky.org

blog.hirokiky.org

DjangoCongressの参加ブログがどれも良いのでまとめておきたい #djangocongress

先日のDjangoCongress JP 2018の参加ブログが続々公開されてて読んでいて楽しい。 どの記事も面白いのでザックリとだけどまとめておいた。あとでdjango-jaのもっと公式的な場所に書き写すかもしんない。

djangocongress.jp

ありがとう。ありがとう。 読みたいので、他にもあったら教えて。

以下、読んだブログ

最終更新: 2018年5月31日

nwpct1.hatenablog.com

blog.mtb-production.info

nikkie-ftnext.hatenablog.com

katekichi.hatenablog.com

thinkami.hatenablog.com

xaro.hatenablog.jp

blog.hirokiky.org

jumpyoshim.hatenablog.com

www.denzow.me

DjangoCongress JP に行ってきた | attakei page

nakagami.blog.so-net.ne.jp

ryu22e.org

koty.hatenablog.com

thinkami.hatenablog.com

farewell-work.hatenablog.com

tokibito.hatenablog.com

medium.com

eng.iridge.jp

medium.com

massa142.hatenablog.com

blog.xoxzo.com