nykergoto’s blog

機械学習とpythonをメインに

Django Congress 2021 に参加しました!

2021/07/03 に開催された Django Congress に参加しました。とても有意義なお話を沢山拝聴でき勉強になりましたし非常に楽しかったです! ありがとうございました!

以下各発表の自分のメモ書きになります。(スライドは随時追加予定です)

Django 3.2 ASGI対応 - こわくない asyncio 基礎とasync viewの使い所

Junya Fukuda san

  • Awsgi / Async View の説明
    • スライドわかりやすい〜
  • async / await のためには ORM の async 対応も必要
    • 現状はまだできてない。
    • 非同期ORM対応の検討中らしい

note

  • 雑な理解しかしていなかったので参考になった。
  • 非同期ORM、楽しそう。入ると、効率がアップすると思うのだけれど、どのぐらいの改善度になるのかなー?

RLSを用いたマルチテナント実装

Takayuki Shimizukawa san

マルチテナントのメリット

  • 各ユーザが同じリソースを使えるので無駄が少ない

マルチテナントのデメリット

  • データが混濁する可能性がある
  • 気合でデータ混濁を防止するのは無理
  • データ混濁をしないような仕組みづくりが必要

マルチテナントの方法

  • スタンドアロン
    • アプリケーションもDBも別
  • テナント単位DB
    • アプリケーションは同じだけれど、テナント単位で別のスキーマのテーブルを使う
  • シャドーマルチテナント
name DB アプリ
スタンドアロン 分離 分離
テナント単位DB 分離・準分離 共有
シャドーマルチテナント DB共有 アプリ共有

DB準分離

  • メリット
    • スキーマで別れているので混濁が起こる可能性が低い
    • django-tenants のようなライブラリもあるよ
  • デメリット
    • テナント数が増えたときのメンテナンスコストが高い
      • migration をテナント数だけ実行する必要がある
      • 例えば 30[s] の migration で 5000 テナントだと1日以上かかる 😭

DB共有

  • メリット
    • メンテコストが低い
  • デメリット
    • 混濁おこるかもよ → RLS を使って行レベルアクセス権限を設定する

RLSとは

  • row level security (行レベルセキュリティ)
  • 行単位でアクセス権を制御する DB の機能

RLSの仕組み

  • ROLE:
    • データ・ベースのテーブル・行権限を決めるもの
    • 対応の行と、今アクセスしているユーザの role との一致で、行単位でのアクセス権限が制御される。
    • たとえば tenant 列を role として設定して role=1 のユーザでアクセスすると tenant = 1 の行だけしか見えない
  • 権限の扱われ方
    • RLSがあるとテーブルアクセス権と行アクセス権の概念が別に存在する
      • テーブルへの select 権限があっても RLS がないと何も見えない
    • POLICY を設定するとマッチする行だけが帰ってくる様になる

Djangoでどう実現する?

  • Django では DB接続のユーザを切り替えるのは難しい
  • ユーザは変えずに set role を使ってセッションのユーザを付与する
  • Django のライフサイクルに role 設定を仕込む
    • テナント作成時に新しい role を追加
    • post_save の signal でテナント作成
    • middleware でテナント判断
      • ログインユーザに応じた role を付与して query 発行するようにする

通常より気にする必要があるポイント

  • クエリ負荷の上昇は、もちろんある。
    • 負荷対策をよりシビアにする必要がある
  • コネクションを分けるのはできない
    • DBの上限接続数が 100 以上にできない。したがってテナントごとコネクションは難しい。
  • 負荷分散
    • テナントごとにクエリを利用するリソースを分けたい → Citus / Hyperscale 利用を検討する
    • 特定テナントごとに別ノードで分散処理できる (テナント1は node1 で実行などできる)

DB共有デメリット対策

  • role設定忘れ内容に
  • バックアップ方法
    • PITRをテナント単位で行う方法
  • 負荷分散リソース

質疑

  • 単体テストはどうする?
    • 今はコンテナあるので、テストのときもポスグレつかえはOK
  • role を定義しているカラムに index 貼れば速度は改善する?
    • 調査しきれていないが、単に数値を設定するのではなくテキスト付与すると良くない

Note

  • 各設定方法のメリットデメリットが整理されていてありがたい。
  • テナント形式のアプリはたまにあるので参考にしよ。

Djangoでのプロジェクトだって型ヒントを運用出来る!

みずき-san: https://speakerdeck.com/mizzsugar/djangodefalsepuroziekutodatutexing-hintowoyun-yong-chu-lai-ru

speakerdeck.com

型ヒントのよいところ

どこから始める?

  • django のコード部分は django-stubs の知識が必要でハードルが高い
  • pure な python 部分から

git pre-commit フック

  • メリット
    • CI が不要
  • デメリット
    • コミット内容と関係ない部分もエラーになる
    • エラーがあるとき、強制的に commit をする方法もあるがオオカミ少年的になる
  • 結局利用しないことに決めた
    • 途中から導入したゆえの大変さ
    • 最初から入れていたらやっていたかも

--strict option

  • mypyはデフォルトでは4つを指摘する
  • strict にするとより細かい内容も指摘する
  • django で strict は必要?
    • django のコードと strict の相性が悪い
      • これは解決したみたい。
    • デフォルトの内容でも十分と判断して strict しないように

CI をいつ入れる?

  • django 関係ない utils module にたいして type がついてから

詰まったポイント

  • AbstractUserModel の継承時の問題
    • [memo] おそらく class の継承全般で発生する問題かな?
  • field と同一名の method 定義
  • related object does not exist がない
  • Queryset.value_list で django-stubs の型が django から消えてる

質疑

  • チームからの反対はなかった?
    • もともと別のプロジェクトに型をつけていた。その時のメンバーは好意的にやってくれていた。
    • 次のプロジェクトにも入れていこうという流れにつながった

Note

  • 型設定のチーム導入の話まで踏み込まれていて学びがおおい
  • mypy 使えてないのでちいさいとこからこつこつ入れていこうと思いました。

Django管理サイトをカスタマイズする前に教えてほしかったこと

akiyoko-san: https://speakerdeck.com/akiyoko/how-to-customize-admin-djangocon-jp-2021

Django 管理サイト

  • みんな使ってる管理サイト
  • 困りごと
    • カスタマイズが大変という意見が多い

基本仕様

  • ログイン条件
    • is_staff / is_active が true
  • permission
    • モデルごと・操作ごとの permission が必要

カスタマイズの難易度

  • かんたん
    • django の用意してくれているカスタム方法を使うやり方
    • 全体をかえる → AdminSite
    • モデルごと → ModelAdmin
  • 難しいこと
    • template のカスタマイズ
    • css のカスタマイズ

template のカスタマイズ

  • 優先度が高いディレクトリに編集したいテンプレートを設定する
  • 直したい部分だけ継承して編集・場合によっては全体まるっと持ってくることも可能
  • [tips] 実際にどのようなテンプレートが使われているかは django-debug-toolbar の template から確認できる

CSS のカスタマイズ

  • 静的ファイルの優先順位を知る
    • template 同様に、ファイルの優先順位があるので、自分が設定したいものが上に来るように適宜設定する。
  • 全体の編集:
    • 管理サイト本体の extrastyle block を override して設定
      • extrastyle は main の css のあとに読み込まれるので優先度高く読み込まれる
    • 設定方法
      • 新しいファイルを読み込むように overide
      • 静的ファイルの場所が優先度が高くなるようにしておく
  • モデル部分のみの編集:
    • model admin の media.css を利用する

admin site のテスト方法

  • そもそも断片的なコードしかないのでどういうテストをすればよいかが自明ではない

テストの方法

  • lxml を使ったテスト
  • Selenium Driver をつかったテスト
    • Selenium で admin 管理画面をテストする専用のテストケースクラスがある
    • スクリーンショットを作成して保存するとかもある
    • 実行時間は長めになるので注意

Note

  • django提供のカスタムばかりメインでやっていたので template / css のカスタム方法の体系的な指針をもらえて嬉しい。
  • 管理画面の可能性を感じた。

未経験者のDjangoでの個人開発

haru-san: https://docs.google.com/presentation/d/1gm0kGhoNLJ8fe4qtdOg5y6kzZk8ZRjBEnZQ9sNui2Hc/edit#slide=id.ge1c975fe8d_0_1

docs.google.com

大変だったこと

  • ORM
  • 認証周りなどなど

なんでそうなっちゃったか

  • コードと挙動の関係性理解が欠如しているママまえに進んでいた
    • Django のコードと実際に発行される SQL の関係性 ...etc
  • 参考にして良いものがわからなかった
  • わからないことがいっぱいあって焦っていた。

反省点

  • コピペでチュートリアルをやっていた
    • 中身を理解せず、動かすことに注力していた
    • 動かす楽しさは大事だけれど、長期的に見て中身を理解することが大事
  • エラー内容の本質理解の欠如
    • なんとなくで理解していた
    • エラー文をちゃんと読まずに表面的対応になってた

良かったこと

  • 設計の意識
  • git を CLI から使う

反省から学んだこと

  • 非公式の情報を参考にするときは以下を気をつける
    • 前提条件が欠かれているのか
    • 中身を自分が理解できる説明か
  • 公式ドキュメントを大事にする
  • 初歩を大事にして、少しづつ応用へと向かっていく
  • 疑問点をそのままにしない

学習はとにかく時間を書けるしかない

質疑

  • なんで django にしたの?
    • 友達がやっていたのでやってみた
  • 振り返りの考え方ができるのはなんでですか?
    • スポーツをやっていて、その中で人と比較して自分を省みることをまなんだ
  • どういう本があったら嬉しい? どういう内容があると嬉しい?
    • ネットで探して出てくる情報は断片的
    • 実際の設計・構成がどうなっているかがわからなかった
      • Django でクリーンアキーテクチャをやろうと思ったときどうやればいいか
      • 具体的にアプリ設計をするときどのような命名ディレクトリにするべきなのか
  • socail auth の設定はどのようにやった?
    • 考えてもわからなかったので質問して解決した
    • 質問をするときに情報をまとめる作業で解決することもあった
  • 今後の興味は?
    • チーム開発のやり方・テストコード
    • 機械学習もやってみたい

note

  • 何ができていなくて、何をしたらいいのかが言語化されていて素敵
  • 17歳すごい

Securing Django Web Applications

Gajendra Deshpande san: https://speakerdeck.com/gcdeshpande/securing-django-applications

speakerdeck.com

  • xml file じゃなくて json にしましょう
  • 英語聞くのに必死でメモできず…

Note

  • こういう情報はどうやって仕入れているのかなーと気になったのですが聞けず… mmm
  • 資料の量がすごい。読み返そう。

Django & Celery in production

Masataka Arai san: https://speakerdeck.com/massa142/django-and-celery-in-production

speakerdeck.com

タスクキューとは

  • producer
    • task を作って broker へとパスする
      • task: 非同期で実行する処理のひとつのまとまりのこと
      • queue: task を入れる入れ物
  • broker
    • もらった task を queue に入れる
    • queue に入っているタスクを consumer へと渡す
  • consumer
    • 実際に task をおこなう (celery worker)

タスクキューにはいいとこ悪いところがあるのでそれを理解して使う必要がある (ex: メール送信などなど)

  • メリット
    • 時間がかかる処理を非同期に逃せる (リクエスト早くなる)
    • 処理が別れているのでスケールしやすい
    • エラーがあってもリトライできる
  • デメリット
    • 複雑化
      • 監視・ログの考え事がふえちゃう
    • 処理の遅延が大きくなる可能性がある

celery 以外のやり方もあるよ

  • RQ
  • FaaS: lambda と SQS

気をつけポイント

  • モデルインスタンス渡しがちだけど、古いデータになることに注意
    • 実行時に最新の instance を取得したいのであれば pk とかを渡すように
  • テスト時には同期的に実行するオプションを入れる

リトライ設計の心得

  • 復帰可能なエラー以外は投げっぱなしにする
  • 復帰可能なものに関しては…
    • 無限にくりかえす
    • 冪等性を担保して何回も実行する
  • 運用でカバーする必要があるものに関しては DB に入れる
  • 目的

タスクへの設定方法

  • 単純なリトライ
    • autoretry_for
  • 複雑なリトライ
    • retry_when_retriable に自分で関数を設定
    • だめだった理由ごとにリトライの方法を書いていく
      • mysql のロック などなど
    • エラーハンドリングの育て方はどうするんだろう

ロギング

  • django-celery-results
    • celery の task protocol = 2 だとネストした dict の深度が 3 になるので注意
  • 運用カバー
    • django-admin から以上設定のものを再起動できるようにしておく
  • 監視
    • celery inspect を使って待ってるタスクを見る
    • 実行待ち時間が長くなると slack に投げる、など

本番環境の更新

  • task 更新時
    • タイミングのずれで昔の引数で呼び出される可能性がある
    • 引数には必ずデフォルト値を設定 & kwargs でハンドリングできるようにしておくことで新旧の呼び出しに対応する
  • task 削除時
    • 昔のサーバーから call される可能性がある。
    • celery はそのままで app サーバーだけ更新する。

Note

  • ナイーブに app と同時に celery server も更新すると良くないのとか考えてなかった。CI 組み込むときも気にしないとな。

理解して使いこなすDjangoのForm機能

フォームの vaidation を少し直すとなったときでもいろんなパラメータがあってよくわからない。

  • django shell をつかおう
    • form を shell から見ることで理解が深まる & テストコードも自然に書ける

Form の構成要素

  • bound field
    • html の作成を担当
  • widge
  • error
    • form.errors にエラーが代入される
    • form から見ると widge の名前が key に errors の配列 (List[Error]) が value に入って取得できる
  • 複数の field にまたがった validation をする場合
    • form.clean に記述する
    • super().clean() を call して各要素の validation を終わったあと validation がおわったデータを使って validation のロジックを記述する
    • ここでエラーになると none-field error になる
    • 特定の key にエラーを入れることもできる (add_errors)
  • 一つの field で validation
    • form のコンストラクタに validators を追加する

Note

  • form の構成から細かく説明いただいていて大変参考になる。

スポンサーセッション

  • (株)日本システム技研さん
    • 設立 昭和51年7月
    • 会場コストのスポンサー。大変ありがたい。
    • 2014年から会社として Django を使おうという流れできていて、当時と比べると今はたくさん日本語の情報が出ていて、隔世の感とのこと。そうなのかー!

まとめ

いろんな新しいことをしれてとても楽しかったです! 開催運営のみなさまありがとうございました!